diff --git a/frontend/miniapp/app.js b/frontend/miniapp/app.js index 1929867..12bd1a4 100644 --- a/frontend/miniapp/app.js +++ b/frontend/miniapp/app.js @@ -62,7 +62,7 @@ App({ onHide: function () {}, globalData: { unread: 0, //未读消息数(tabbar红点共享缓存) - unreadFetchedAt: 0, //上次拉取未读数的时间,各 tabBar 实例共用,避免切 Tab 重复请求 + unreadSeq: 0, //未读数写入序号,用来丢弃过期响应 appShowAt: 0, //最近一次 App.onShow 的时间 refreshDemandId: 0, //操作后需要刷新状态的需求ID(跨页面通知列表页) }, diff --git a/frontend/miniapp/custom-tab-bar/index.js b/frontend/miniapp/custom-tab-bar/index.js index 23263b2..340258f 100644 --- a/frontend/miniapp/custom-tab-bar/index.js +++ b/frontend/miniapp/custom-tab-bar/index.js @@ -1,5 +1,6 @@ import TabMenu from './data'; import { fetchMessageUnreadCount } from '../services/message/fetchMessage'; + Component({ data: { active: 0, @@ -9,7 +10,7 @@ Component({ lifetimes: { attached() { - // 先用全局缓存渲染,避免切换 tab 时红点闪没。网络请求交给 show,并与其他实例共用节流 + // 先用全局缓存渲染,避免切换 tab 时红点闪没。网络请求交给 show const app = getApp(); const unread = app && app.globalData ? Number(app.globalData.unread) || 0 : 0; if (unread > 0) { @@ -18,9 +19,13 @@ Component({ }, }, - // 当前 tab 显示时刷新。30s 内各实例只发一次请求 + // 每次显示当前 Tab 时拉一次未读数,停在页面上不再重复请求 pageLifetimes: { show() { + const app = getApp(); + if (app && app.globalData) { + app.globalData.unreadOwner = this; + } this.refreshUnread(); }, }, @@ -47,11 +52,10 @@ Component({ }, /** - * 从服务端拉取未读消息数 - * 未登录时不显示红点。节流记在 globalData,切换 Tab 新建的 tabBar 实例也会共用 - * 30s 内只发一次;消息页改未读数走 setUnread,不走这里 + * 从服务端拉取未读消息数。未登录时不显示红点 + * 进行中的请求不重复发;消息页 setUnread 会作废更早的响应,避免红点被旧结果盖回去 */ - refreshUnread(force = false) { + refreshUnread() { const app = getApp(); const token = (wx.$util && wx.$util.getToken && wx.$util.getToken()) || ''; if (!token) { @@ -61,32 +65,34 @@ Component({ } return; } - const now = Date.now(); - const last = app && app.globalData ? Number(app.globalData.unreadFetchedAt) || 0 : 0; - if (!force && now - last < 30000) { - if (app && app.globalData) { - this.setData({ unread: Number(app.globalData.unread) || 0 }); - } - return; - } if (app && app.globalData && app.globalData.unreadFetching) { + this.setData({ unread: Number(app.globalData.unread) || 0 }); return; } + const seq = ((app && app.globalData && app.globalData.unreadSeq) || 0) + 1; if (app && app.globalData) { + app.globalData.unreadSeq = seq; app.globalData.unreadFetching = true; - app.globalData.unreadFetchedAt = now; } const done = () => { - if (app && app.globalData) { + if (app && app.globalData && app.globalData.unreadSeq === seq) { app.globalData.unreadFetching = false; } }; fetchMessageUnreadCount().then((res) => { + if (app && app.globalData && app.globalData.unreadSeq !== seq) { + return; + } if (res.code == 1) { const unread = Number(res.data?.unread_count) || 0; this.setData({ unread }); if (app && app.globalData) { app.globalData.unread = unread; + // 请求返回时人可能已经切到另一个 Tab,把红点写到正在显示的那一份 + const owner = app.globalData.unreadOwner; + if (owner && owner !== this && typeof owner.setData === 'function') { + owner.setData({ unread }); + } } } }).catch(() => {}).then(done, done); @@ -101,7 +107,8 @@ Component({ const app = getApp(); if (app && app.globalData) { app.globalData.unread = unread; - app.globalData.unreadFetchedAt = Date.now(); + app.globalData.unreadSeq = (app.globalData.unreadSeq || 0) + 1; + app.globalData.unreadFetching = false; } }, },