在web worker中使用fetch实例详解

Oria ·
更新时间:2024-05-16
· 1241 次阅读

目录

1.Web Worker意义

2. 主线程的使用

创建

通信

错误处理

关闭

3. 子线程的使用

和主线程的通信

加载其他脚本

关闭

4. 在WebWorker中使用fetch

5. 实现思路

1.Web Worker意义

由于 JS 是单线程的,费时的 JS 操作将会导致整个页面的阻塞。Web Worker 提供了创建多线程的方法,将一些耗时且 UI 无关的工作交给 worker,可提高页面的使用体验。

限制:

同源策略:worker 线程执行的脚本要和当前页面同源

API 限制:

不能操作 DOM

不能使用 window 的全局变量,但可以使用 navigator 和 location 对象

不能使用 alert、confirm 方法

无法读取本地文件

和主线程不在一个上下文环境,通讯要通过 postMessage 完成

2. 主线程的使用 创建

创建一个子线程,要传入一个脚本的 URL。如果该脚本加载失败,则 Worker 会静默失败

const worker = new Worker('url');

如果要在本文件中描述执行的内容,可以用 Blob 和 window.URL.createObjectURL 生成一个 URL

function createWorker(f) { const blob = new Blob(['(' + f.toString() +')()']); const url = window.URL.createObjectURL(blob); const worker = new Worker(url); return worker; } 通信

主线程 => 子线程

worker.postMessage(param);

参数可以是任意类型,包括二进制数据。但传递是拷贝形式而不是引用形式。因此对于大数据会存在性能问题。

子线程 => 主线程

worker.onmessage = function (event) { console.log('Received message ' + event.data); } 错误处理 worker.onerror(function (e) { console.log([ 'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message ].join('')); }); 关闭 worker.terminate(); 3. 子线程的使用

子线程中无法使用 window,self 代表全局对象

和主线程的通信

主线程 => 子线程

self.addEventListener('message', function (e) { self.postMessage('Received: ' + e.data); }, false);

子线程 => 主线程

self.postMessage('something'); 加载其他脚本

在子线程中加载其他脚本:

importScripts('script1.js', 'script2.js'); 关闭 self.close(); 4. 在WebWorker中使用fetch

网络请求是和DOM无关且可能耗时较长的操作,worker线程支持使用Fetch,是适合放在worker中进行的操作。

而要在worker中使用fetch,如果每次都要自己处理线程间的通信的话,会十分麻烦,因此我对通信进行了封装,写成了一个可以直接使用的库。

安装依赖:

npm i web-worker-fetch

使用时先实例化一个WF对象,然后就可以像使用fetch一样在worker中使用fetch:

import WebWorkerFetch from "web-worker-fetch"; const wf = new WebWorkerFetch(); wf.fetch("url", { method: "POST", // *GET, POST, PUT, DELETE, etc. mode: "cors", // no-cors, *cors, same-origin cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached credentials: "same-origin", // include, *same-origin, omit headers: { "Content-Type": "application/json" // 'Content-Type': 'application/x-www-form-urlencoded', }, redirect: "follow", // manual, *follow, error referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url body: JSON.stringify(data) // body data type must match "Content-Type" header }).then((res) => console.log(res));

除此之外,借鉴 axios 的思路,配置中可以提供 requestInterceptorresponseInterceptor,对请求参数和返回数据做统一处理

5. 实现思路

这个库的封装主要是解决了两个问题:

发送请求时如何把参数传递给worker线程

请求结束后如何从worker线程获取结果

对于第一个问题,主线程使用 ostMessage 向worker线程传递参数。

对于第二个问题,worker线程通过 self.postMessage 向主线程传递消息,主线程通过 worker.onmessage 监听消息。

此时就引出了问题所在:如果多次使用 wf.fetch 发送请求,那么在一个请求完成后,worker线程触发的消息将让所有请求处都认为请求已完成。

因此,在每次请求时,使用一个fetchId确定该请求做唯一性。将该id传给worker线程,后续worker线程向主线程通信时也会带上这个id。

在主线程中监听onmessage事件时,判断id是否和自己的请求id一致,只有在相同时才做处理。

具体的实现大家可以移步仓库源码,实际上也非常简单。

以上就是在web worker中使用fetch实例详解的详细内容,更多关于web worker使用fetch的资料请关注软件开发网其它相关文章!



worker Web fetch

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章