郑州企业自助建站,网络营销推广方法与策略,南昌网页制作,成都那家网站做的好本文不保证能说明透彻#xff0c;因为它本来就存在着混乱#xff0c;但力求讲到点子上。比较下面这几个的执行顺序setTimeoutsetIntervalsetImmediate (nodejs 支持#xff0c;new Promise(cb) 和 promise.then(cb)(promise 是 Promiose 的实例)process.nextTick(nodejs)还有…本文不保证能说明透彻因为它本来就存在着混乱但力求讲到点子上。比较下面这几个的执行顺序setTimeoutsetIntervalsetImmediate (nodejs 支持new Promise(cb) 和 promise.then(cb)(promise 是 Promiose 的实例)process.nextTick(nodejs)还有一些另外的(暂时不考虑)socket.on(close, cb) close callback(nodejs)分类同步执行new Promise(cb) cb 代码会同步执行其实不属于考虑范畴了microTask 微任务process.nextTick tickTaskpromise.then(cb) microTaskmicroTask (在 nodejs)可以进一步划分为 tickTask 和 microTask都是微任务队列同类型的微任务先进先执行优先级是 tickTask microTaskmacroTask 宏任务setTimeoutsetInterval 优先级同 setTimeout谁先被推到 timers 队列谁就先执行setImmediate在不同类型宏任务切换的间隙一旦微任务队列有任务则会把微任务队列先执行完然后继续执行下一个类型的宏任务队列。(注意是切换的时候如果已经进入执行阶段是让该类型的宏任务执行完然后检查微任务队列如果宏任务执行时又加入了同类型的宏任务则会在下一个循环里面执行)进入 timers 或者 check 或者其他的宏任务队列时如果 microTask 任务队列中没有任务则会在执行完优先执行的宏任务队列之后再检查 microTask 任务队列(注意如果某个 macroTask 执行时推入了新的 microTask它依然会先把这个类型的宏任务队列执行完然后切换下一个类型宏任务队列时先执行微任务)如果有则执行完 microTask然后进入下一个类型的 macroTask 队列这里有一个非确定情况setImmediate 和 setTimeout 的执行顺序在 nodejs 中不是固定的(nodejs 开发者这么说)。 For example, if we run the following script which is not within an I/O cycle (i.e. the main module), the order in which the two timers are executed is non-deterministic, as it is bound by the performance of the process”做个测试下面的执行是不确定的没有实际的意义setTimeout(() {console.log(1 setTimeout)setTimeout(() {console.log(2 setTimeout)}, 0)setImmediate(() {console.log(3 setImmediate)})}, 0)setImmediate(() {console.log(4 setImmediate)})nodejs可能4 setImmediate1 setTimeout3 setImmediate2 setTimeout也可能1 setTimeout4 setImmediate3 setImmediate2 setTimeoutsetTimeout 有一个隐形前提它的第二个参数也就是延迟执行的时间最小是 4ms即使指定的 0另外注意它是 n ms 之后才可能执行并不是 n ms 时就会执行它的执行时间是不确定的只能知道在 n ms 之前它不会执行。setInterval 回调内如果是一个 while 循环即使时间设定的 0,它也不会推无限多个回调到 timers 队列中而是要等到这个执行完才会把下一个回调推入 timers 队列用 while 执行 2S 之后清除掉 interval发现回调只执行了一次而不是执行很多次。看下面的例子这说明 setInterval 会推一个回调到 timers 队列然后执行然后再推下一个回调。let count 0setTimeout(() {console.log(1 setTimeout)}, 0)const i setInterval(() {console.log(2 setInterval)countif (count 5) {clearInterval(i)}setTimeout(() {console.log(3 setTimeout , count)}, 0)}, 0)setTimeout(() {console.log(4 setTimeout)}, 0)---1 setTimeout2 setInterval4 setTimeout3 setTimeout 12 setInterval3 setTimeout 22 setInterval3 setTimeout 32 setInterval3 setTimeout 42 setInterval3 setTimeout 5nodejs 事件循环上述基本都是 macroTask 宏任务setTimeout(() {console.log(1 setTimeout)setTimeout(() {console.log(2 setTimeout)}, 0)setImmediate(() {console.log(3 setImmediate)})setTimeout(() {console.log(4 setTimeout)}, 0)setImmediate(() {console.log(5 setImmediate)})}, 0)这个结果说明执行过程是整个队列执行完再执行下一个队列下面结果说明在同一事件循环内 check 队列会执行完之后再去执行 timers 队列。(check 未必比 timers 快)1 setTimeout3 setImmediate5 setImmediate2 setTimeout4 setTimeout如果在 check 队列执行期间推入 microTask 任务那就先让当前 check 队列执行完然后再执行 microTask再执行 timers 队列。setTimeout(() {console.log(1 setTimeout)setTimeout(() {console.log(2 setTimeout)}, 0)setImmediate(() {console.log(3 setImmediate)new Promise(res res()).then(() {console.log(4 promise)})process.nextTick(() {console.log(5 nextTick)})})setTimeout(() {console.log(6 setTimeout)}, 0)setImmediate(() {console.log(7 setImmediate)})}, 0)执行结果两个 setImmediate 被放到 check 队列check 队列中的 setImmediate 要先全部执行完然后再下一步而下一步过程中 microTask 就会执行。1 setTimeout3 setImmediate7 setImmediate5 nextTick4 promise2 setTimeout6 setTimeout注意下面代码和上面代码的区别setTimeout(() {console.log(1 setTimeout)setTimeout(() {console.log(2 setTimeout)}, 0)setImmediate(() {console.log(3 setImmediate)})new Promise(res res()).then(() {console.log(4 promise)})process.nextTick(() {console.log(5 nextTick)})setTimeout(() {console.log(6 setTimeout)}, 0)setImmediate(() {console.log(7 setImmediate)})}, 0)---1 setTimeout5 nextTick4 promise3 setImmediate7 setImmediate2 setTimeout6 setTimeout题目题目 1setTimeout setInterval 是不是相同优先级是否被推到同一个队列setTimeout(() {console.log(1 timeout)}, 0)setInterval(() {console.log(2 interval)}, 0)setTimeout(() {console.log(3 timeout)}, 0)setInterval(() {console.log(4 interval)}, 0)setTimeout(() {console.log(5 timeout)}, 0)题目 2setTimeout(() {console.log(1 setTimeout)setTimeout(() {console.log(2 setTimeout)}, 0)setImmediate(() {console.log(3 setImmediate)setImmediate(() {console.log(4 setImmediate)})process.nextTick(() {console.log(5 nextTick)})})setImmediate(() {console.log(7 setImmediate)})setTimeout(() {console.log(8 setTimeout)}, 0)}, 0)总结微任务(microTask)是大爷宏任务(macroTask)得让着微任务但是一旦让一个类型的宏任务开始执行那就得等这个类型的宏任务执行完然后才能执行微任务在宏任务中被推入队列的宏任务得在下一轮才能开始执行这一轮没新宏任务的份。欢迎大家关注我的掘金和公众号算法、TypeScript、React 及其生态源码定期讲解。