js中的事件循环机制很有意思。从很多面试题中也可以看出,考察简单的setTimeout也是在考察这个机制。之前单纯的想,因为函数执行的很快,即使setTimeout的执行时间为0,也不会马上输出,而是等函数执行完再输出。这只对了一半。其实它的运行机制就是js中的事件循环机制。在这个循环机制中,与callStack和taskqueue有关。1.js的事件循环机制事件循环机制,简单来说就是在执行上下文的过程中,将函数压入栈和出栈。函数在执行前被压入栈中,执行后从栈中弹出。如果遇到回调函数、ajax、setTimeout等一些异步操作,就会交给浏览器的其他模块去执行。执行后,回调函数将被放入任务队列。当所有的调用栈都执行完后,任务队列中的函数就会被执行。举个简单的例子:console.log(1);setTimeout(function()看一下执行的内部过程1.执行第一句,放入调用栈,输出12.第一句出栈出栈,执行第二句,因为是异步执行,交给其他模块处理3.执行完后,将回调函数放入taskqueue4.执行下一句,同第一步,语句入栈执行,输出35语句出栈,此时调用栈为空,执行任务队列任务,输出2,因此,输出结果符合预期。其次,如果加入了Promise,advanced是如何工作的呢?我们知道Promise的回调函数不是Incoming,而是使用then来调用。因此Promise中定义的函数应该立即执行,然后是它的回调函数,放到the队列队列。还提到了一个重要的概念:macro-task包括:script(整体代码)、setTimeout、setInterval、setImmediate、I/O、UI渲染。微任务包括:process.nextTick、Promises、Object.observe、MutationObserver执行顺序:清空函数调用栈,只剩下全局执行上下文,然后开始执行所有微任务。在执行完所有可执行的微任务之后。循环再执行宏任务中的一个任务队列,执行完再执行所有的微任务,一直循环下去。(functiontest(){setTimeout(function(){console.log(4)},0);newPromise(functionexecutor(resolve){console.log(1);for(vari=0;i<10000;i++){i==9999&&resolve();}console.log(2);}).then(function(){console.log(5);});console.log(3);})()执行过程:1.GosetTimeout,交给其他模块执行,执行完后回调放到宏任务中。2、遇到Promise,立即执行里面的函数,输出1。3、循环开始时,遇到resolve()时,修改Promise状态为fulfill。继续执行,输出2。4.遇到then,将回调放到微任务中。5.继续执行,输出3。6.调用栈执行完毕。开始执行微任务中的回调函数,输出5.7.微任务执行完毕后,开始执行宏任务中的回调函数,输出4.8.End。【本文为专栏作家“谢军”原创稿件。转载可通过作者微信取得联系公众号(jingfeng18)】点此查看该作者更多好文
