Web Worker
关于进程和线程
- 一个程序运行时,就是一个进程,这里的程序可以是一段代码,也可以是一个exe应用程序
- 线程是程序中一个执行流
- 一个进程包含n个线程,同一个进程中的多个线程之间的所有变量共享
- 多个进程之间变量不共享,同一个变量,各自有一份拷贝存在于每个进程中,互不影响
如果理解 Javascript 是单线程
代码依次按顺序执行
作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM
这决定了它只能是单线程,否则会带来很复杂的同步问题
比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
单线程的 javascript 如何实现异步操作
概念
- 同步:会逐行执行代码,会对后续代码造成阻塞,直至代码接收到预期的结果之后,才会继续向下执行任务
- 异步:调用之后先不管结果,继续向下执行任务,常见的有:setTimeout, promise, 事件回调等
实现原理
- 浏览器是多线程的

- 主线程负责自上而下顺序执行,当遇到setTimeout函数后,便将其交给
定时器线程去执行 定时器线程执行完之后,将 满足触发主线程条件的 回调函数放到任务队列中,任务队列中的任务不会马上执行- 待主线程代码执行完毕,才开始
任务队列代码的执行
宏任务 & 微任务
- 异步任务分为两种:宏任务、微任务
- 两者包含

- 优先执行
微任务,可以理解为:一个人去银行办理业务,一个业务办理完成后,柜员会问是否还有其他业务需要办理,这个时候的其他业务相当于是微任务,如果没有,才会继续叫号下一位(宏任务)
浏览器的 Event Loop
- 执行全局script的同步代码,形成一个
执行栈; 碰到异步代码按宏任务和微任务区分,将宏任务加入宏任务队列,微任务加入微任务队列,任务队列的代码不立即执行 执行栈里的代码执行完毕后被清空,查看微任务队列是否有任务- 若有,则将
微任务队列加入执行栈,再在当前执行栈中,对微任务和宏任务按以上顺序循环执行,形成一个Event Loop - 若无,则查看
宏任务队列是否有任务- 若有,则将
宏任务队列加入执行栈,再在当前执行栈中,对微任务和宏任务按以上顺序循环执行,形成一个Event Loop - 若无,则结束
- 若有,则将
- 若有,则将
console.log('start');
setTimeout(() => {
console.log('time1');
Promise.resolve().then(() => {
console.log('promise1');
})
}, 0);
setTimeout(() => {
console.log('time2');
Promise.resolve().then(() => {
console.log('promise2');
})
}, 0);
Promise.resolve().then(() => {
console.log('promise3');
});
console.log('end');
// 输出
// start
// end
// promise3
// time1
// time2
// promise1
// promise2
HTML5提出的 Web Worker 标准
- 在独立于js主线程的后台线程中,执行一个新的脚本
- 不影响主线程,不影响js的单线程本质
Web Worker 的限制
- 不能操作DOM: 新的线程下操作DOM,会产生浏览器渲染的同步问题;
- 不能使用
document,window,parent对象,但可以访问location,navigator对象 - Worker线程与主线程必须是同源,且不能使用
file://文件系统的文件 - Worker线程与主线程之间,使用
postMessage通讯 - 可以使用
XMLHttpRequest对象发送AJAX请求