单线程的js如何异步执行

2021-02-26  本文已影响0人  肥羊猪

JavaScript是脚本语言,它需要在一个宿主环境里才能运行,接触较多的宿主环境就是--浏览器

浏览器多线程.png

JavaScript引擎线程称为主线程,它负责解析JavaScript代码;其他可以称为辅助线程,这些辅助线程便是JavaScript实现异步的关键

异步任务却又分为两种:一种叫“宏任务”(MacroTask 或者 Task),一种叫“微任务”(MicroTask)


异步任务.png
console.log(1);
setTimeout(() => {
    console.log(2);
}, 0);
Promise.resolve().then(() => {
    console.log(3);
});
console.log(4);
//1 - 4 - 3 - 2
因为 setTimeout属于宏任务,而Promise属于微任务

浏览器的Event Loop

1.执行全局Script同步代码,形成一个执行栈;
2.在执行代码时当遇到如上异步任务时便会按上文所描述的将宏任务回调加入宏任务队列,微任务回调加入微任务队列;
3.然而,回调函数放入任务队列后也不是立即执行;会等待执行栈中的同步任务全部执行完清空了栈后引擎才能会去任务队列检查是否有任务,
如果有那便会将这些任务加入执行栈,然后执行!
4.执行栈清空后,会先去检查微任务队列是否有任务,逐一将其任务加入执行栈中执行,期间如果又产生了微任务那继续将其加入到列队末尾,
并在本周期内执行完,直到微任务队列的任务全部 清空,执行栈也清空后,再去检查宏任务队列是否有任务,取到队列队头的任务放入到执行栈中执行,
其他可能又会产生微任务,那当本次执行栈中的任务结果清空后又会去检查微任务队列...
5.引擎会循环执行如上步骤,这就是Event Loop
浏览器的Event Loop.png
console.log('start');
setTimeout(() => {
    console.log('time1');
    Pormise.resolve().then(() => {
        console.log('promise1');
    })
}, 0);
setTimeout(() => {
    console.log('time2');
    Pormise.resolve().then(() => {
        console.log('promise2');
    })
}, 0);
Pormise.resolve().then(() => {
    console.log('promise3');
});
console.log('end');
//start - end - promise3 - timer1 - promise1 - timer2 - promise2
上一篇 下一篇

猜你喜欢

热点阅读