什么是node事件环,实际上就是node运行代码的机制,比如一个任务什么时候会执行以及该代码执行顺序。
在说这个node事件环之前我们需要简单的了解下node的特点:
(1)单线程
(2)不适合复杂计算场景的使用但是适用于高I/O场景。
node代码执行机制(如图所示):
- V8引擎解析JavaScript脚本。
- 解析后的代码,调用Node API。
- libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
- V8引擎再将结果返回给用户。
此外还涉及到一个同步与异步,阻塞与非阻塞的慨念(因为node是单线程的)。
阻塞与非阻塞指代的是调用者,同步与异步指代的是被调用者。
有了上面的概念那么就开始说node的任务。
ok,一张图说白了node机制,那么现在就来看看这里面到底是怎么回事,让我们首先就看两点微任务和宏任务,暂时把微任务和宏任务中间的忽略掉。
宏任务有 setTimeout MessageChannel setImmediate
先看微任务,process.nextTick是最快的他适合干调用完同步代码之后在执行某些事但是这个有缺点不能递归!!!要不然进程就卡死在这。
再看宏任务 setTimeout setImmediate 这两个谁快不一定,因为setTimeout有4ms的延迟node准备执行的时候 可能会小于4ms。
代码:
setTimeout(() => { console.log('timeout'); }); setImmediate(() => { console.log('setImmediate') });
那么现在来个复杂点的例子,大家先猜下运行的结果。
setTimeout(() => { console.log('timeout1'); Promise.resolve().then(data=>{ console.log('promise2'); }) }, 1000); Promise.resolve().then(data=>{ // 1ms console.log('promise1'); setTimeout(() => { // 1001 console.log('timeout2'); }, 1000); })
首先我们知道微任务再宏任务之前所以先输出promise1 timeout1这一点相信大家都能猜的到,那么还有两项promise2和timeout2输出的顺序是不一定的,因为node微任务执行完后 会将到达时间的宏任务执行完再执行微任务而且node的微任务执行必须等待某个队列执行完 切换到下一个队列时才会清空微任务,所以才造成promise2和settimeout2输出的顺序是不一定的。
顺手说句poll 阶段下一个永远是 check阶段!
代码:
fs.readFile('text.txt',(err,data)=>{ setTimeout(() => { console.log('timeout2'); }); setImmediate(() => { console.log('setImmediate'); }); });