水平不够,只能整理一下知乎大神的回答,勉强度日这样子
在一个事件循环里,会有两个主要的队列:task queue 和 micro-task quene。
其中 task 包括: script(整体代码),setTimeout,setInterval,setImmediate,MessageChannel,I/O,UI rendering;
(HTML5 中规定 setTimeout 的最小时间延迟是 4ms,也就是说理想环境下异步回调最快也是4ms才能触发。所以Vue 模拟 task 时,优先使用 setImmediate 和 MessageChannel,目的是让回调异步且尽早调用。)
micro-task包括:process.nextTick,Promise(浏览器原生的Promise),Object.observe,MutationObserver;
MutationObserver 实现 micro-task 的DEMO:
function nextTick (nextTickHandler) { var counter = 1 var observer = new MutationObserver(nextTickHandler) var textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) }
timerFunc() }
事件循环的过程如下:
- 浏览器先执行第一个 task ,在其执行过程中产生的 task 将被push入 task queue、在其执行过程中产生的 micro-task 将被push入 micro-task queue;
- 第一个task完成后,浏览器开始按顺序执行所有的 micro-task,在其执行过程中产生的 task 将被push入 task queue、在其执行过程中产生的 micro-task 将被push入 micro-task queue,直到 micro-task queue 里的所有任务执行完毕,这时浏览器会执行一次渲染来更新视图(由于有可能一直在产生micro-task,导致一直在执行micro-task,下一个task等待时间太长,各个环境设置了队列最大长度:长度最大1e4,Node版本v6.9.1);
- 重复上面的过程,浏览器执行 task queue 里的下一个任务......
所以:
setTimeout(function(){ console.log(1) },0); new Promise(function(resolve){ console.log(2) for( var i=0 ; i<10000 ; i++ ){ i==9999 && resolve() } console.log(3) }).then(function(){ console.log(4) }).then(function(){ Promise.resolve().then(function(){ console.log(5) }) }); console.log(6);
结果是:
2, 3, 6, 4, 5, 1