使用 Web Worker 进行 api 次调用

Using web worker for api calls

我正在尝试找到一种使用网络工作者执行 api 调用的简洁方法,到目前为止,我在客户端进行了此操作:

工人-client.js

export const workerFetch = (method = "get", url = "/", data = {}) =>
  new Promise((resolve, reject) => {
    const listener = `worker_fetch_${url}_${new Date()}`;
    window.lootWorker.postMessage({
      cmd: "worker_fetch",
      payload: { method, url, data, listener }
    });
    window.addEventListener(
      "message",
      ({ data }) => {
        if (data.cmd === listener) {
          if (data.success) resolve(data.data);
          else reject(data.data);
        }
      },
      false
    );
  });

因此可以从客户端调用此函数并提供一些参数。 在 web worker 内部

工人-thread.js

const workerFetch = ({ method = "get", url = "", data = {}, listener = "" }) => {
  fetch({ method, url, data })
    .then(({ data }) => {
      self.postMessage({ cmd: `worker_fetch_${listener}`, success: true, data });
    })
    .catch(error => {
      self.postMessage({ cmd: `worker_fetch_${listener}`, success: false, data: error });
    });
};

self.addEventListener(
  "message",
  ({ data }) => {
    switch (data.cmd) {
      case "worker_fetch":
        workerFetch(data.payload);
        break;
      default:
        return null;
    }
  },
  false
);

理论上这是可行的,但我担心在客户端冒泡那些事件侦听器,因此这个问题是为了看看是否有实现此功能的通用方法,该功能侧重于性能?毕竟我们这样做是为了从主线程中卸载一些东西。

我对这个模式有一些保留意见:

  1. 请记住,只有 response 的处理发生在另一个线程上,因此您需要确保在卸载所有负载之前处理您的有效负载是一个瓶颈获取请求。

  2. 如果担心冒泡,应该把addEventListener里的useCapture设置成true,用stopPropagation防止冒泡到children

  3. 您假设所有提取调用按顺序 return。现在您要卸载给工作人员,这将无法再得到保证。所以你需要用某种标识符来标记每个请求。

您如何实施第 3 条还有待商榷。如果您关注性能,则可能需要研究一些性能 UUID 生成器。

最后,似乎有一个 npm 包实现了这个功能:fetch-worker