『前端碎碎念』系列会纪录我日常平凡看书或许看文章遇到的题目,平常都是比较基本然则轻易忘记的知识点,你也能够会在口试中遇到。 我会查阅一些材料并能够加上本身的明白,来纪录这些题目。更多文章请前去我的个人博客
这个题目是有关实行递次和Event Loop的。关于Event Loop和使命行列等观点,能够先浏览我援用中的文章,本文重要剖析一些存在的迷惑点。
下面这个例子比较典范:
setImmediate(function(){
console.log(1);
},0);
setTimeout(function(){
console.log(2);
},0);
new Promise(function(resolve){
console.log(3);
resolve();
console.log(4);
}).then(function(){
console.log(5);
});
console.log(6);
process.nextTick(function(){
console.log(7);
});
console.log(8);
//输出效果是3 4 6 8 7 5 2 1
在诠释输出效果之前,我们来看几个观点:
macro-task: script (团体代码),setTimeout, setInterval, setImmediate, I/O, UI rendering.
micro-task: process.nextTick, Promise(原生),Object.observe,MutationObserver
除了script团体代码,micro-task的使命优先级高于macro-task的使命优先级。
个中,script(团体代码) ,能够明白为待实行的一切代码。
所以实行递次以下:
第一步. script团体代码被实行,实行历程为
建立setImmediate macro-task
建立setTimeout macro-task
建立micro-task Promise.then 的回调,并实行script console.log(3); resolve(); console.log(4); 此时输出3和4,虽然resolve调用了,实行了然则团体代码还没实行完,没法进入Promise.then 流程。
console.log(6)输出6
process.nextTick 建立micro-task
console.log(8) 输出8
第一个历程事后,已输出了3 4 6 8
第二步. 由于其他micro-task 的 优先级高于macro-task。
此时micro-task 中有两个使命根据优先级process.nextTick 高于 Promise。
所以先输出7,再输出5
第三步,micro-task 使命列表已实行终了,家下来实行macro-task. 由于setTimeout的优先级高于setIImmediate,所以先输出2,再输出1。
全部历程形貌起来像是同步操作,实际上是基于Event Loop的事宜轮回。
关于micro-task和macro-task的实行递次,可看下面这个例子(来自《深入浅出Node.js》):
//到场两个nextTick的回调函数
process.nextTick(function () {
console.log('nextTick耽误实行1');
});
process.nextTick(function () {
console.log('nextTick耽误实行2');
});
// 到场两个setImmediate()的回调函数
setImmediate(function () {
console.log('setImmediate耽误实行1');
// 进入下次轮回
process.nextTick(function () {
console.log('强势插进去');
});
});
setImmediate(function () {
console.log('setImmediate耽误实行2');
});
console.log('一般实行');
书中给出的实行效果是:
一般实行
nextTick耽误实行1
nextTick耽误实行2
setImmediate耽误实行1
强势插进去
setImmediate耽误实行2
process.nextTick在两个setImmediate之间强行插进去了。
但运转这段代码发明效果倒是如许:
一般实行
nextTick耽误实行1
nextTick耽误实行2
setImmediate耽误实行1
setImmediate耽误实行2
强势插进去
朴先生写那本书的时刻,node最新版本为0.10.13,而我的版本是6.x
老版本的Node会优先实行process.nextTick。
当process.nextTick行列实行完后再实行一个setImmediate使命。然后再次回到新的事宜轮回。所以实行完第一个setImmediate后,行列里只剩下第一个setImmediate里的process.nextTick和第二个setImmediate。所以process.nextTick会先实行。
而在新版的Node中,process.nextTick实行完后,会轮回遍历setImmediate,将setImmediate都实行终了后再跳出轮回。所以两个setImmediate实行完后行列里只剩下第一个setImmediate里的process.nextTick。末了输出”强势插进去”。
详细完成可参考Node.js源码。
关于优先级的另一个比较清楚的版本:
观察者优先级
在每次轮训搜检中,各观察者的优先级分别是:
idle观察者 > I/O观察者 > check观察者。
idle观察者:process.nextTick
I/O观察者:平常性的I/O回调,如收集,文件,数据库I/O等
check观察者:setImmediate,setTimeout
setImmediate 和 setTimeout 的优先级
看下面这个例子:
setImmediate(function () {
console.log('1');
});
setTimeout(function () {
console.log('2');
}, 0);
console.log('3');
//输出效果是3 2 1
我们晓得如今HTML5划定setTimeout的最小间隔时候是4ms,也就是说0实际上也会别默认设置为最小值4ms。我们把这个耽误加大
上面说到setTimeout 的优先级比 setImmediate的高,实在这类说法是有条件的。
再看下面这个例子,为setTimeout增加了一个耽误20ms的时候:
setImmediate(function () {
console.log('1');
});
setTimeout(function () {
console.log('2');
}, 20);
console.log('3');
//输出效果是3 2 1
setTimeout耽误20ms再实行,而setImmediate是马上实行,居然2比1还先输出??
尝尝打印出这个顺序的实行时候:
var t1 = +new Date();
setImmediate(function () {
console.log('1');
});
setTimeout(function () {
console.log('2');
},20);
console.log('3');
var t2 = +new Date();
console.log('time: ' + (t2 - t1));
//输出
3
time: 23
2
1
顺序实行用了23ms, 也就是说,在script(团体代码)实行完之前,setTimeout已过期了,所以当进入macro-task的时刻setTimeout依旧优先于setImmediate实行。假如我们把这个值调大一点呢?
var t1 = +new Date();
setImmediate(function () {
console.log('1');
});
setTimeout(function () {
console.log('2');
},30);
console.log('3');
var t2 = +new Date();
console.log('time: ' + (t2 - t1));
//输出
3
time: 23
1
2
setImmediate早于setTimeout实行了,由于进入macro-task 轮回的时刻,setTimeout的定时器还没到。
以上试验是基于6.6.0版本Node.js测试,实际上在遇到相似这类题目的时刻,最好的方法是参考规范,并查阅源码,不能死记观点和递次,由于规范也是会变的。包含此文也是自学总结,经供参考。
参考:
https://www.zhihu.com/questio…
https://segmentfault.com/a/11…
http://www.jianshu.com/p/837b…