1. 引言
引入Web Worker作为一种解决方案,可以在浏览器中实现多线程。
2. Web Worker基础
创建一个新的worker线程:
var worker = new Worker(URL);
在worker线程中,我们可以监听message事件,并通过postMessage方法回应主线程:
self.addEventListener('message', function(e) {
self.postMessage(e.data);
}, false);
在主线程中,我们也可以通过同样的方式来接收worker线程的回应:
worker.addEventListener('message', function(e) {
console.log('Worker said: ', e.data);
}, false);
3. Web Worker的使用场景
-
大量计算:如果你的网页需要进行大量的计算,可能会阻塞主线程,导致用户界面无法响应。在这种情况下,你可以创建一个Web Worker,把计算任务交给它,从而避免阻塞主线程。
例如,你可以使用Web Worker来计算一个大数的斐波那契数列或者执行复杂的数学运算。
-
处理大数据:如果你需要处理大量的数据,例如排序或者搜索,也可以使用Web Worker。同样,这可以避免阻塞主线程。
例如,如果你需要对一个非常大的数组进行排序,可以把这个任务交给Web Worker。
-
网络请求:你也可以在Web Worker中进行网络请求。这样,即使网络请求需要很长时间,也不会影响用户界面的响应。
例如,你可以在Web Worker中使用Fetch API或者XMLHttpRequest来获取数据。
-
图像处理:Web Worker也可以用于图像处理,例如图像解码、图像分析等。
例如,你可以在Web Worker中使用Canvas API来处理图像。
-
实时数据处理:在处理实时数据流,如WebSocket或WebRTC时,Web Worker可以用于在后台处理这些数据。
以上是Web Worker的一些常见使用场景。需要注意的是,由于Web Worker运行在单独的线程中,不能直接访问DOM或者window对象的某些属性,因此并不是所有的任务都适合交给Web Worker。在决定是否使用Web Worker时,你需要考虑这些限制。
4. Web Worker的限制
1. 同源限制
分配给 worker 的脚本文件,必须与主线程脚本文件同源。
2. DOM 限制
worker 线程无法读取主线程所在网页的 DOM 对象,无法使用 document、window、parent 这些对象,可以使用 navigator 和 location 对象。
3. 通信限制
worker 线程和主线程不再同一个上下文环境中,不能直接通信,必须通过消息完成。
4. 脚本限制
worker 线程不能执行 alert 方法和 confirm 方法,但是可以发出 ajax 请求。
5. 文件限制
worker 线程无法读取本地文件,不能打开文件系统,所加载的脚本,必须来自网络,不能是 file:// 文件。
5. worker 线程怎样监听主线程的消息的?如何发送消息的?worker 线程又是如何关闭的?
Worker 线程内部需要有一个监听函数,监听 message 事件。
// 监听
self.addEventListener('message', function (e) {
// 发送消息
self.postMessage('You said: ' + e.data);
}, false);
12345
关闭 worker 线程
1)主线程关闭 worker 线程
worker.terminate()
2)worker 线程关闭
self.close()
6、主线程和 worker 线程的 API
| 主线程 | worker 线程 |
|---|---|
Worker.onerror:指定 error 事件的监听函数 | self.name: Worker 的名字 |
Worker.onmessage:指定 message 事件的监听函数 | self.onmessage:指定 message 事件的监听函数 |
Worker.onmessageerror:指定 messageerror 事件的监听函数 | self.onmessageerror:指定 messageerror 事件的监听函数 |
Worker.postMessage():向 Worker 线程发送消息 | self.close():关闭 Worker 线程 |
Worker.terminate():立即终止 Worker 线程 | self.postMessage():向产生这个 Worker 线程发送消息 |
self.importScripts():加载 JS 脚本 |
7. 结论
目前 Worker 还没有被大规模使用,所以围绕 Worker 也没有太多的实践和架构。但是遇见大量计算得情况,还是很值的尝试使用Worker得,比如大量数据懒加载得表格求和等。