js event Loop的机制

5 篇文章 0 订阅
3 篇文章 0 订阅
enent Loop 即时事件循环,在浏览器或者node环境下js单线程运行时不会阻塞的一种机制,也就是我们所理解的异步原理

js的运行机制是分为堆、栈和队列,如图所示:
在这里插入图片描述
而在js机制中,js是分为宏任务(MacroTask)也叫Task和微任务(MicroTask)的,浏览器在运行的时候会首先清空微任务,然后才会执行宏任务。

mask宏任务:
script全部代码、setTimeout、setInterval、setImmediate(浏览器暂时不支持,只有IE10支持,具体可见MDN)、I/O、UI Rendering

MicroTask微任务:
Process.nextTick(Node独有,vue里面有用)、Promise、Object.observe(废弃)、MutationObserver,详情可查看这里

举例如下

     console.log('script start');

        setTimeout(function () {
            console.log('setTimeout');
        }, 0);

        Promise.resolve().then(function () {
            console.log('promise1');
        }).then(function () {
            console.log('promise2');
        });
        console.log('script end');
        注意:setTimeout是宏任务,Promise是微任务(如果是new Promise则是宏任务)

第一次执行:
执行同步代码,将宏任务(Tasks)和微任务(Microtasks)划分到各自队列中。
log:script start、script end
第二次执行:
执行宏任务后,检测到微任务(Microtasks)队列中不为空,执行Promise1,执行完成Promise1后,调用Promise2.then,放入微任务(Microtasks)队列中,再执行Promise2.then。
log:script start、script end、promise1、promise2
第三次执行:
当微任务(Microtasks)队列中为空时,执行宏任务(Tasks),执行setTimeout callback,打印日志。
log:script start、script end、promise1、promise2、setTimeout

 console.log('script start')  //1

        async function async1() {
            await async2()
            console.log('async1 end') //5
        }
        async function async2() {
            console.log('async2 end') //2
        }
        async1()

        setTimeout(function () {
            console.log('setTimeout') //8
        }, 0)

        new Promise(resolve => {
            console.log('Promise') //3
            resolve()
        })
            .then(function () {
                console.log('promise1') //6
            })
            .then(function () {
                console.log('promise2') //7
            })

        console.log('script end')//4

首先,打印script start,调用async1()时,返回一个Promise,所以打印出来async2 end。
每个 await,会新产生一个promise,但这个过程本身是异步的,所以该await后面不会立即调用。
继续执行同步代码,打印Promise和script end,将then函数放入微任务队列中等待执行。
同步执行完成之后,检查微任务队列是否为null,然后按照先入先出规则,依次执行。
然后先执行打印promise1,此时then的回调函数返回undefinde,此时又有then的链式调用,又放入微任务队列中,再次打印promise2。
再回到await的位置执行返回的 Promise 的 resolve 函数,这又会把 resolve 丢到微任务队列中,打印async1 end。
当微任务队列为空时,执行宏任务,打印setTimeout。

Process.nextTick()(vue中就是使用这个来进行插队的)

let bar;

setTimeout(() => {
  console.log('setTimeout');
}, 0)

setImmediate(() => {
  console.log('setImmediate');
})
function someAsyncApiCall(callback) {
  process.nextTick(callback);
}

someAsyncApiCall(() => {
  console.log('bar', bar); // 1
});

bar = 1;

结果:
bar 1
setTimeout
setImmediate
首先执行
process.nextTick(callback);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值