js运行机制

js是单线程的;js是单线程的;js是单线程的。重要的事情说三遍。

换而言之,在某个时间段内,js只会做一件事,只有当完成某件事时,才会去干下一件事。

看到这里有些看官已经把手举起来了:我难道不知道单线程是什么意思吗?骚年,别急,先把砖放下。单线程当然是一次只能干一件事,但是干完这件事,接下去先做哪件事呢?是按语句的先后顺序吗?那我们就来试试看:上代码

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');

看到这段代码,我会心一笑,拿起键盘,哒哒哒敲下:

script start
setTimeout
promise1
promise2
script end

自信满满,意气风发

骚年,等等。待老夫将这段代码输出验证一下,在装13不迟。输出结果:

script start
script end
promise1
promise2
setTimeout

页面在加载的时候,js是按语句顺序执行,但是遇到加载图片,加载音频这种耗时久的任务怎么办?难道等到加载完成在继续执行吗,万一网络情况不好,那么用户可能只能看到白屏了,原地爆炸。所以优秀的程序员将这些任务有分为了同步任务和异步任务。异步任务完成时,通知主线程,进而更新页面。

注意:Event Table中保存的是各种需要执行的异步任务,而Event Queue队列中是已经完成并注册的异步任务的回调函数。也就是说当一个异步任务在Event Queue中成功注册了回调函数,那么这个异步任务肯定是已经执行完毕了。

 

当主线程中执行玩同步任务时(此时JS引擎空闲),就会去读取Event Queue中的函数,进入主线程执行。js引擎中的monitoring process进程会持续去检查主线程是否空闲,如果空闲就会去Event Queue中检查是否有需要执行的函数。这整个循环就形成了Event Loop。

回到之前的题目,setTimeout,Promise这些都属于异步任务,那么怎么确定这些在Event Queue中的地位呢?这里又要引入一个概念:宏任务,微任务。

宏任务和微任务会进入对应的Event Queue,当执行一个宏任务时,会从头到尾执行完毕,期间不会执行微任务,只有当本次宏任务执行完毕后,才会执行所有的微任务;当微任务执行完毕,回去检查是否还有需要执行的宏任务,如此往复。

宏任务包括:主体script、setTimeout、setIntervalt、

微任务包括:Promise、process.nextTick

了解了这些,让我们回到最开始的那题。

第一步:运行主体script代码,从头到尾运行,所以先输出script start,遇到了属于宏任务的setTimeout,将它放入Event Queue;紧接着遇到了属于微任务的Promise,也放入Event Queue(与setTimeout不是同一个),执行最后一句,输出 script end;

第二步:执行完成了宏任务,紧接着执行所有的微任务,输出promise1、promise2;

第三步:检查是否还有未执行的宏任务,很显然还有一个setTimeout,输出setTimeout,结束。

 

参考文章:https://juejin.im/post/59e85eebf265da430d571f89

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值