如何访问 Service Worker 中的 Web Worker?

How can I access Web Workers in a Service Worker?

我最近经常使用 serviceworker 并且经常 运行 遇到这样一种情况,我想在将其存储到 serviceworker 缓存之前处理一些获取的原始数据 - 示例使用案例是处理一个大的原始文本文件以删除不必要的白色 space。这样,对我的 http 请求的缓存响应就已经是 "optimized".

我在想为什么不在 webworker 中这样做,但是,唉,经过大量搜索,我没有找到任何关于如何在 serviceworker 中访问 webworker 的想法。这不像我可以使用 postMessage 传入 webworker 上下文。

问题:
如何访问 Service Worker 中的 Web Worker?

目前无法从服务工作者内部访问网络工作者。这在未来可能会改变,相关标准问题是https://github.com/whatwg/html/issues/411

请注意,可以在由普通网页生成的 Web Worker 中使用缓存存储 API,因此理论上您可以在 Service Worker 的上下文之外执行您建议的操作。

这是个人偏好的问题,而不是严格的指导方针,但我不喜欢修改从网络返回的数据然后使用缓存存储 API 来保存它的模式在合成 Response 对象中。我更喜欢使用缓存存储 API 来保存您从网络返回的内容的精确副本,这样无论请求是从网络还是从缓存中完成,您的受控页面看起来都是一样的。

我以前使用过的一种模式,以您建议的方式使用 web worker 具有额外的好处,就是以类似的方式使用 IndexedDB。如果响应已经在 IndexedDB 中,那么你就使用它,如果没有,那么你启动一个 web worker 来处理网络请求和处理,然后将结果存储在 IndexedDB 中以备将来使用。

Here's an example of some code to do this, making use of a lot of ES2015+ features, along with the promise-worker and idb-keyval 个异步代码库。

import PromiseWorker from 'promise-worker';
import idbKeyValue from 'idb-keyval';

export default async (url, Worker) => {
  let value = await idbKeyValue.get(url);
  if (!value) {
    const promiseWorker = new PromiseWorker(new Worker());
    value = await promiseWorker.postMessage(url);
    // Don't await here, so that we can return right away.
    idbKeyValue.set(url, value);
  }
  return value;
};

然后工作人员可以查看一些东西 like this(将 Markdown 转换为 HTML):

import 'whatwg-fetch';
import MarkdownIt from 'markdown-it';
import registerPromiseWorker from 'promise-worker/register';

const markdown = new MarkdownIt();

registerPromiseWorker(async url => {
  const response = await fetch(url);
  const text = await response.text();
  return markdown.render(text);
});

如果您要处理大量数据,这种方法将开始变得不那么有意义,因为与仅使用缓存相比,序列化会产生开销,并且缺少 streaming support直接存储API。