“Web Workers”在WHATWG里已经是LS,被大多数浏览器支持,详细可看caniuse。
在讲述Web Workers究竟是什么之前,我们先回头看一下历史遗留问题。
痛点:单线程
浏览器端的javascript属于单线程环境--你不能同时运行多个脚本,也做不到一边运行着复杂运算一边响应着用户的交互事件。
考虑这么一个例子:
我希望用户打开我的Web App后,在正常使用着应用的同时,
偷偷地帮我运行一些耗时很长的破解工作(可能是破解密码或其他)。
先不考虑这个实例是否道德,而实际上传统浏览器也不提供多线程技术让我们实现这种功能。虽然异步、事件机制(如利用setInterval、setTimeout等)在一定程度上能模拟“并行”,但始终不能实现流畅的多线程执行,更别说利用多核CPU。
什么是Web Workers
Web Workers出现的目的就是解决上述的这种单线程。利用Web Workers技术,我们可以在浏览器端实现多线程。Web Workers是:
An API for running scripts in the background independently of any user interface scripts.
Web Workers能帮助你创建独立的、不与页面线程相互影响的域,来执行你的javascript代码。
创建一个Worker
下文会用“window域”指代页面代码所在的作用域。
创建Worker只需要简单的两步,一是注备好你要独立线程执行的代码,二是new一个Worker:
// secret-job.js
while(true) {
// Do secret jobs.
}
<!-- index.html -->
<script>
let secretWorker = new Worker('secret-job.js');
</script>
上面代码做了:
- 在window域里创建一个新的Worker,并赋值给secretWorker
- Worker创建的同时,会创建一个新的DedicatedWorkerGlobalScope
- 这个DedicatedWorkerGlobalScope是一个与window域完全独立的作用域;这两个作用域下没有任何共同的东西,而且由两个线程分别执行
- "secret-job.js"的代码会在DedicatedWorkerGlobalScope里执行
就这样,你实现了“使用一个新的线程执行特定的js代码”。
创建一个新的Worker时发生了什么
- 得到一个Worker实例
- 创建一个新的WorkerGlobalScope
- 创建一个新的线程
- 参数对应的js文件的代码会以WorkerGlobalScope作为context,在这个新的线程里执行
但:
- WorkerGlobalScope是什么?
- DedicatedWorkerGlobalScope又是什么?
- 在WorkerGlobalScope下为什么很多东西如window、document都拿不到?
这些东西我会在以后说明,而下篇我们要先讨论一个更重要的问题:域(线程)间的通信。