写点什么

重学 JS | Web Workers 让 JS 存在多线程环境

用户头像
梁龙先森
关注
发布于: 2021 年 01 月 20 日
重学JS | Web Workers让JS存在多线程环境

我们都知道 JavaScript 是单线程的,只有等上个任务执行完,才能执行下一个任务。当执行一些密集型或者高延迟的任务时,会造成主线程的阻塞,浏览器页面冻结。Web Worke 的出现,为 JavaScript 创造多线程环境。允许主线程创建 Worker 线程,并将任务分配给 worker 线程。并且 Worker 线程是在后台运行,与主线程互不干扰。所以可以将耗时、密集型任务分配给 Worker 线程,等执行完成再通知主线程。


看看使用 Web Worker 的简单例子:

// 主线程 index.js
// 传入一个要执行的js文件,实例化Web Worker// 此时会导致浏览器下载js文件,但不会执行let worker = new Worker('worderDemo.js')// 监听Worker传递过来的信息worker.onmessage = function(event){ const {data} = event}// 监听Worker内部错误worker.onerror = function(event){ const { filename, // 文件名 lineno, // 代码行数 message // 完整的错误信息 } = event}// 给Worker发送消息启动执行worker.postMessage({ type:'cmd', data:'start'})// 停止worker的工作,内部代码会立即停止执行,后续的过程都不会再发生worker.terminate()
复制代码


// Web Worker:  worderDemo.js 
// 监听主线程的发送消息self.onmessage = function(event){ const {data} = event self.postMessage({ type:'end', data:'Worker处理完数据了' })}
复制代码

这个例子里的 Worker 只能为指定的页面服务,不能在页面共享的,因此也称为“专用 Worker”。关于页面共享的“Worker”目前尚未有完成规范。


代码里为啥用 self 进行监听呢?这里看看 Worker 的作用域。

Worker 所执行的 JavaScript 是完全独立的一个作用域,不与页面共享作用域,且 Web Worker 中的全局对象指向的是 worker 对象本身,所以 this 指向 worker 对象,这里 self 也引用 worker 对象。在这个特殊域中,无法访问 DOM,也无法通过任何形式影响页面的外观。


当然,Web Worker 本身也是一个最小化的运行环境,不过跟页面环境是没法比。存在以下可操作对象:

  1. 最小化的 navigator 对象,包括 onLine、appName、appVersion、userAgent 和 platform 属性

  2. 只读的 location 对象

  3. setTimeout()、setInterval()、clearTimeout()和 clearInterval()方法

  4. XMLHTTPRequest 构造函数


最后总结下几个注意点:

  1. 同源策略:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源

  2. 脚本限制:不能执行 alert()和 confirm()方法,但可以使用 XMLHTTPRequest

  3. 文件限制:Worker 无法读取本地文件(file://),所加载的文件必须来源网络

  4. DOM 限制:Worker 不能操作 Dom,也无法使用 window/doument 这些,但可以使用 navigator 等。

  5. 通信联系:Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。


至此,简单学习了下 Web Workers 应用。

发布于: 2021 年 01 月 20 日阅读数: 19
用户头像

梁龙先森

关注

脚踏V8引擎的无情写作机器 2018.03.17 加入

还未添加个人简介

评论

发布
暂无评论
重学JS | Web Workers让JS存在多线程环境