如何处理Service Worker安装事件中被拒绝的Promise



我遇到一个情况,需要从Service Worker安装事件中捕获一个被拒绝的承诺并显示一条错误消息。

我设置了一个名为testsw.js的测试ServiceWorker,它会立即抛出一个被拒绝的承诺,如下所示:

console.log("Hello from SW");
self.addEventListener('install', function (evt) {
evt.waitUntil(Promise.reject(new Error("Test")));
})

我正在使用以下代码注册Service Worker:

navigator.serviceWorker.register('/testsw.js')
.then(function (reg) {
console.log("Service worker successfully registered.", reg);
})
.catch(function (err) {
console.error("Service worker failed to register.", err);
})

在这种情况下,catch函数永远不会被命中,注册Service worker会导致控制台输出:

testsw.js:1 Hello from SW
testsw.js:3 Uncaught (in promise) Error: Test
at testsw.js:3
(anonymous) @ testsw.js:3
(index):468 Service worker successfully registered. ServiceWorkerRegistration

我已经尝试过将被拒绝的promise封装在一个函数中,并在evt.waitUntil()中调用它,以及抛出一个简单的Error,但没有任何更改。Service Worker仍然处于冗余状态,这很好,但我仍然需要知道安装失败了。

我是否误解了在Service Worker安装中被拒绝的承诺是如何工作的?注册中是否存在错误配置,使其始终命中then块,即使承诺被拒绝?如果做不到这一点,ServiceWorkerRegistration类或其他类中是否有内容会告诉我们服务工作者安装或更新失败?

如果有区别的话,这在Chrome 77和Edge 83中进行了测试,但没有成功

只要加载了脚本并注册了辅助程序,注册承诺就会实现,无论它是否安装失败(甚至可能不再需要安装(。要检查安装是否失败,您需要侦听来自安装工作者的statechange事件:

navigator.serviceWorker.register('/testsw.js').then(function (reg) {
console.log("Service worker successfully registered.", reg);
if (reg.installing) {
reg.installing.onstatechange = function(e) {
if (e.target.state == 'installed') {
console.log("Service worker successfully installed.");
} else if (e.target.state == 'redundant') {
console.log("Service worker failed to install.");
}
};
}
}).catch(function (err) {
console.error("Service worker failed to register.", err);
});

如果您还想显示安装失败的原因,那么您似乎必须自己处理install处理程序中的错误,并将消息传递到原始页面。也许还可以尝试在安装工作线程上侦听error事件。然而,你可能不得不手动触发这些,因为未经处理的承诺拒绝不会自动被捕获:

console.log("Hello from SW");
self.addEventListener('install', function (evt) {
const installation = Promise.reject(new Error("Test"));
evt.waitUntil(installation);
installation.catch(err => {
self.clients.matchAll({includeUncontrolled: true}).then(clients => {
for (const client of clients)
client.postMessage({type: 'error', message: err.message});
});
});
});

最新更新