如何处理 Service Worker 安装事件中被拒绝的 Promise?
How do I handle a rejected Promise in a Service Worker install event?
我有一个案例,我需要从 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
我已经尝试将被拒绝的 promise 包装在一个函数中并在 evt.waitUntil()
中调用它,以及抛出一个普通的错误,没有任何变化。 Service Worker 还是进入了冗余状态,这很好,但我仍然需要知道安装失败。
我是否误解了被拒绝的承诺在 Service Worker 安装中的工作方式?注册中是否存在某些错误配置,即使承诺被拒绝,它也会始终命中 then
块?如果做不到这一点,ServiceWorkerRegistration
class 或其他地方是否有什么东西会告诉我们服务工作者未能安装或更新?
如果它有所不同,这在 Chrome 77 和 Edge 83 中进行了测试,但没有成功。
一旦加载脚本并注册 worker,注册承诺就会履行,无论安装是否失败(甚至可能不再需要安装)。查看是否安装失败,需要监听statechange
events from the installing worker:
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 on the installing worker. You might however have to fire these manually, as 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});
});
});
});
我有一个案例,我需要从 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
我已经尝试将被拒绝的 promise 包装在一个函数中并在 evt.waitUntil()
中调用它,以及抛出一个普通的错误,没有任何变化。 Service Worker 还是进入了冗余状态,这很好,但我仍然需要知道安装失败。
我是否误解了被拒绝的承诺在 Service Worker 安装中的工作方式?注册中是否存在某些错误配置,即使承诺被拒绝,它也会始终命中 then
块?如果做不到这一点,ServiceWorkerRegistration
class 或其他地方是否有什么东西会告诉我们服务工作者未能安装或更新?
如果它有所不同,这在 Chrome 77 和 Edge 83 中进行了测试,但没有成功。
一旦加载脚本并注册 worker,注册承诺就会履行,无论安装是否失败(甚至可能不再需要安装)。查看是否安装失败,需要监听statechange
events from the installing worker:
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 on the installing worker. You might however have to fire these manually, as 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});
});
});
});