在web worker中使用fetch实例详解

11-17 144阅读 0评论

?=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的资料请关注云初冀北其它相关文章!

免责声明
本站提供的资源,都来自网络,版权争议与本站无关,所有内容及软件的文章仅限用于学习和研究目的。不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,我们不保证内容的长久可用性,通过使用本站内容随之而来的风险与本站无关,您必须在下载后的24个小时之内,从您的电脑/手机中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。侵删请致信E-mail:Goliszhou@gmail.com
$

发表评论

表情:
评论列表 (暂无评论,144人围观)

还没有评论,来说两句吧...