ServiceWorker 如何通过向所有订阅者推送来触发刷新/重新加载?
Posted
技术标签:
【中文标题】ServiceWorker 如何通过向所有订阅者推送来触发刷新/重新加载?【英文标题】:How a ServiceWorker can trigger a refresh/reload by a push to all subscribers? 【发布时间】:2021-11-04 14:03:21 【问题描述】:这是我想要开发的过程:
带有 serviceWorker 的页面 UserA 和 UserB 仅接受来自该页面的通知行为:
如果用户修改页面,则会通知其他用户(移动/桌面已经可以使用)现在我想如果 userA 修改页面:
如果页面已经在 UserB 浏览器上打开,它会自动刷新 如果用户B点击通知:页面刷新但似乎:
ServiceWorker 无法调用“重新加载” 像 setInterval 这样检查上次更新的技巧在 android chrome 上不起作用(肯定是为了带宽?)所以我的问题是:
是否有一种方法可以让服务器推送 serviceWorker 事件以调用每个订阅者的重新加载,即使页面已经在他们的浏览器上打开?换句话说:在页面更新时,serviceWorker 命令订阅者重新加载
这样的 serviceworker 代码失败:
if (client.url == self.registration.scope && 'focus' in client)
client.postMessage('reload'); // DOESN'T WORK
return client.focus();
android/chrome 上的 setinterval 失败代码:
setInterval(async function()
const response = await fetch('/lastupdatetimestamp',
method: 'get',
headers: 'Content-Type': 'application/json'
);
const json= await response.json();
if(LASTUP<json.up.lastdate)
window.location.reload()
LASTUP=json.up.lastdate
, 30000);
有什么想法吗?
【问题讨论】:
【参考方案1】:我终于踏出了第一步:
服务器发送推送 -> serviceworker 显示通知 -> 点击通知 -> 打开窗口并重新加载
在 serviceWorker.js 中
self.addEventListener('push', function (event) ...
self.addEventListener('notificationclick', async function(event)
event.notification.close();
await event.waitUntil(clients.matchAll(
type: "window",
includeUncontrolled: true
).then(function(clientList)
for (var i = 0; i < clientList.length; i++)
var client = clientList[i];
if (client.url == self.registration.scope && 'focus' in client) //
client.postMessage('reload'); // <= TRIGGER 'RELOAD' EVENT HERE
return client.focus();
if (clients.openWindow)
return clients.openWindow(self.registration.scope);
));
);
在 app.js 中
function initPostMessageListener()
console.log("event listener message")
navigator.serviceWorker.addEventListener('message', function(e)
var message = e.data;
console.log("ON A UN MESSAGE")
switch (message)
case 'reload':
window.location.reload(true);
break;
default:
console.warn("Message '" + message + "' not handled.");
break;
);
在注册SW的app.js中调用initPostMessageListener()
所以 SW.js 处理 notificationClick 然后打开浏览器窗口(如果存在)并重新加载它
【讨论】:
以上是关于ServiceWorker 如何通过向所有订阅者推送来触发刷新/重新加载?的主要内容,如果未能解决你的问题,请参考以下文章
您如何向从应用程序本身订阅主题的用户发送 Firebase 推送通知
如何使用 GCP 在 pubsub 模型中一次向所有订阅者发送消息