服务工作者中的全局错误处理是如何工作的?

How does global error handling work in service workers?

我发现 https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/onerror 上面写着:

The onerror property of the ServiceWorkerContainer interface is an event handler fired whenever an error event occurs in the associated service workers.

但是我无法在 Chrome (v51) 中使用它。在主应用程序的范围内,我 运行 来自控制台的以下代码:

navigator.serviceWorker.onerror = function(e) { console.log('some identifiable string' + e); };

然后在active service worker的范围内我触发了一个任意错误:

f(); // f is undefined

结果是通常的 "Uncaught ReferenceError: f is not defined(…)" 错误消息,但它不是通过我的全局 onerror 处理程序记录的。

MDN 页面说这个 API 自 v40 以来在 Chrome 中得到支持,但是 navigator.serviceWorker.onerror 最初是未定义的,这让我相信它没有实现。有人熟悉这个吗?

也许您曾尝试像这样在 navigator.serviceWorker 容器上设置 onerror 处理程序:

// no effect outside service worker script
navigator.serviceWorker.onerror = function() {...};

错误处理程序必须从在服务工作者脚本self.onerror中设置(self在这里是一个特殊的variable/attribute ServiceWorkerGlobalScope)。 onerror 回调仅提供一条错误消息。

// inside service worker script
self.onerror = function(message) {
  console.log(message);
};

或者,您可以监听 service worker 的 error 事件,其中包含包含错误位置的 ErrorEvent

// inside service worker script
self.addEventListener('error', function(e) {
  console.log(e.filename, e.lineno, e.colno, e.message);
});

这是 demo。请务必从 DevTools > Resources > Service Workers(在左侧面板) 中删除服务工作者,因为它将填充这些失败的服务工作者注册:

我已经在一个 service worker 实例中验证了以下浏览器支持 onerror

  • Chrome 51(稳定)和 53(金丝雀)
  • 火狐 47
  • Opera 38(稳定)和 39(开发)

更新:

So when MDN describes the ServiceWorkerContainer interface, that is referring to self (ServiceWorkerGlobalScope) and not navigator.serviceWorker?

我认为这仅适用于 onerror 属性(可能也适用于那里的其他事件),我猜规范尚未更新以反映商定的实施.. .

Service Workers 工作组已决定将 onerrorServiceWorkerContainer 移至 Service Worker 实例,如 GitHub (slightlyoff/ServiceWorker #198) 中所述:

kinu commented on Apr 2, 2014

sgtm2. For error reporting (onerror stuff) we could probably do similar? E.g. moving .onerror handler from container to SW object, so that doc can explicitly know which SW the error is coming from (though it may need to attach handlers to multiple SWs).

然后在相关问题 (slightlyoff/ServiceWorker #104) 中有一个后续评论表明 onerror 在容器上没有用处:

jakearchibald commented on Apr 3, 2014

Thinking about the use-cases (following from #198)…

navigator.serviceWorker.onerror or navigator.serviceWorker.pending.onerror (whichever it becomes) are not useful for logging errors back to the server, as errors can happen outside of the life of any page. onerror inside the worker itself is best for that.

.pending.onerror is useful if you're updating the UI in response to an update. So maybe it's better as a statechange, although you'd need somewhere to put the error message.

That leaves errors that happen before the SW instance is created. AppCache has an error event that covers network-related update failures, and also parse failures. However, once again we'd lose any errors that happened outside the life of a page.