【问题标题】:How do I handle a rejected Promise in a Service Worker install event?如何处理 Service Worker 安装事件中被拒绝的 Promise?
【发布时间】:2020-11-04 14:56:22
【问题描述】:

我有一个案例,我需要从 Service Worker 安装事件中捕获被拒绝的承诺并显示错误消息。

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

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

我已经尝试将被拒绝的承诺包装在一个函数中并在evt.waitUntil() 中调用它,并抛出一个普通的错误,没有任何变化。 Service Worker 仍然处于冗余状态,这很好,但我仍然需要知道安装失败。

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

如果有影响的话,这是在 Chrome 77 和 Edge 83 中测试的,但没有成功。

【问题讨论】:

  • Promise.reject(new Error("Test")) 后面添加catch 可以吗?
  • 怎么样?您的意思是将evt.waitUntil() 行包装在try-catch 块中吗?
  • evt.waitUntil() 收到promise,因此您可以将catch 添加到promise,明白了吗?

标签: javascript promise service-worker


【解决方案1】:

只要脚本被加载并且worker已经注册,注册承诺就会履行,无论它是否安装失败(它甚至可能不再需要安装)。检查是否安装失败,需要从installing worker监听statechange events

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 events。但是,您可能必须手动触发这些,如 unhandled promise rejections don't get caught automatically:

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});
        });
    });
});

【讨论】:

  • 完美!我以为我忽略了一些东西。谢谢!
猜你喜欢
  • 2021-12-18
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 2015-04-26
  • 2018-08-26
  • 1970-01-01
相关资源
最近更新 更多