使用Web Worker独立线程处理耗时请求

/post/webworker article cover image

当遇到一些大数据量请求发送非常耗时,但又不得不在前端处理时,比如一次性推10万+数据。 一方面是服务器压力,再者就是如果用户想要看到最终处理结果那么就会一直等待用户体验就会很差。 那么使用Web Worker在后台分批进行请求就很适合这种场景。

参考资料

新建Worker线程

<u>必须是来自网络的脚本</u>

js
const blob = new Blob(['(' + pushTask.toString() +')()']);
const url = window.URL.createObjectURL(blob);
const worker = new Worker(url);

主线程通过postMessage方法向Worker发送消息启动任务

<u>可传递任意javascript类型数据</u>

js
worker.postMessage({
    param,
    ...
});

接受来自Worker的消息推送

<u>可以处理一些请求完成的回传及首位</u>

js
worker.onmessage = function (res) {
	// 拿到Worker推送过来的数据进行的逻辑处理
    //...

    // 进程连接断开后network将不保留历史请求响应
    // worker.terminate();
}

// 错误事件捕获
worker.onmessageerror = function(err) {
	console.warn(err);
}

Worker中通过self监听主线程的消息推送

<u>self指向DedicatedWebWokerGlobalScope</u>

js
self.addEventListener('message', function(e) {
  // 获取从主线程传递过来的传输
  // 保存在时间对象的data中
  let { param } = e.data;

  // 请求逻辑
  // ...

  // 逻辑处理完毕后,发送结果到主线程.
  // 会被上面实例后的worker.onmessage接收到
  self.pushMessage(res);
})

在Worker中使用importScripts引入同源站点的脚本

<u>Worker中不能直接使用主线程的方法如果任务中依赖其他库需要单独引入</u>

js
const baseDir = location.origin + '/xxx';

self.importScripts(baseDir + '/static/lib/polyfill.min.js')
self.importScripts(baseDir + 'qs.js')
self.importScripts(baseDir + 'axios.js');

// 也可以同时引入多个
//self.importScripts('a.js', 'b.js', ...);

实际场景中这种大数据量且信息敏感的业务请求一般都会由服务端语言本身多线程优势来处理,但遇到这种必须前端临时处理的情况Web Worker就提供了非常适合的选择。