【web-worker】浅析 useWorker 库如何只需函数方法即可在 worker 内运行;如何区分 Web Socket、Web Worker和Service Worker?
useWorker Usage
import React from 'react';
import { useWorker } from '@koale/useworker';
const numbers = [...Array(5000000)].map((e) => ~~(Math.random() * 1000000));
const sortNumbers = (nums) => nums.sort();
const Example = () => {
const [sortWorker] = useWorker(sortNumbers);
const runSort = async () => {
const result = await sortWorker(numbers); // non-blocking UI
console.log(result);
};
return (
<button type="button" onClick={runSort}>
Run Sort
</button>
);
};
源码解析与最简实现
Demo
最简实现
// create worker
const createWWorker = (fn) => {
console.log('worker run');
let promise = {};
const jobRunner = (options) => (e) => {
const [userFuncArgs] = e.data;
return Promise.resolve(options.fn(...userFuncArgs))
.then((result) => {
postMessage(['SUCCESS', result]);
})
.catch((error) => {
postMessage(['ERROR', error]);
});
};
const blobCode = `
onmessage=(${jobRunner})({
fn: (${fn}),
})
`;
const blob = new Blob([blobCode], { type: 'text/javascript' });
const jsUrl = URL.createObjectURL(blob);
const worker = new Worker(jsUrl);
worker.addEventListener('message', (e) => {
const [status, result] = e.data;
switch (status) {
case 'SUCCESS': {
promise.resolve(result);
break;
}
default:
promise.reject(result);
break;
}
if (jsUrl) {
worker.terminate();
URL.revokeObjectURL(jsUrl);
promise = {};
}
});
const runWorker = (...restArgs) =>
new Promise((resolve, reject) => {
promise.resolve = resolve;
promise.reject = reject;
worker.postMessage([restArgs]);
});
return runWorker;
};
// usage
const worker = createWWorker(bubbleSort);
const result = await worker(bigNumbers);
const blobCode = `
onmessage=(${jobRunner})({
fn: (${fn}),
})
`;
const blob = new Blob([blobCode], { type: 'text/javascript' });
const jsUrl = URL.createObjectURL(blob);
const worker = new Worker(jsUrl);
const script = document.createElement('script');
const script = document.createElement('script');
script.innerText = `const test = 333; document.addEventListener('click', () => {
console.log(test);
})`;
document.body.appendChild(script);
通过生成 Blob 创建资源 Url
const blob = new Blob([blobCode], { type: 'text/javascript' });
const jsUrl = URL.createObjectURL(blob);
区分 Web Socket、Web Worker 和 Service Worker
Web Socket
Web Worker
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
引用自阮一峰老师的文章《Web Worker 使用教程》
Service Worker
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 kshao-blog-前端知识记录!
评论