You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
int uv_run(uv_loop_t* loop, uv_run_mode mode) {
int timeout;
int r;
int ran_pending;
r = uv__loop_alive(loop);
if (!r)
uv__update_time(loop);
while (r != 0 && loop->stop_flag == 0) {
uv__update_time(loop);
uv__run_timers(loop);
ran_pending = uv__run_pending(loop);
uv__run_idle(loop);
uv__run_prepare(loop);
timeout = 0;
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
uv__io_poll(loop, timeout);
uv__run_check(loop);
uv__run_closing_handles(loop);
if (mode == UV_RUN_ONCE) {
/* UV_RUN_ONCE implies forward progress: at least one callback must have
* been invoked when it returns. uv__io_poll() can return without doing
* I/O (meaning: no callbacks) when its timeout expires - which means we
* have pending timers that satisfy the forward progress constraint.
*
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
* the check.
*/
uv__update_time(loop);
uv__run_timers(loop);
}
r = uv__loop_alive(loop);
if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
/* The if statement lets gcc compile it to a conditional store. Avoids
* dirtying a cache line.
*/
if (loop->stop_flag != 0)
loop->stop_flag = 0;
return r;
}
Event Loop(事件循环)
在Node的官网中有事件循环操作顺序的简化概览:
每阶段的作用:
setTimeout()
和setInterval()
的调度回调函数。setImmediate()
调度的之外),其余情况 node 将在适当的时候在此阻塞。setImmediate()
回调函数在这里执行。socket.on('close', ...)
。在每次运行的事件循环之间,Node.js 检查它是否在等待任何异步 I/O 或计时器,如果没有的话,则完全关闭。
上面这幅图就是Node事件循环的总体图。对应的代码是在"deps/uv/src/unix/core.c"中(Node版本为v14.0.0,以unix为例)。
这里涉及到libuv,现在不探究libuv。只需要知道代码的作用(总体原理)就好。在Node.js Event Loop 的理解 Timers,process.nextTick()的评价里有对代码详细的注释。
Event Loop通过while不断循环,总是从timers开始,到close callbacks结束,然后又从新开始。
nextTick/Promise
在这个循环中,没有出现nextTick和Promise的身影。但是nextTick和Promise执行的时机是有规定的:每阶段执行完成后执行。意思是在timers执行完后会检查执行nextTick和Promise(当然在第一次执行时,会首先执行next Tick和Promise),后面几个阶段都是这样的。
nextTick和Promise 还有一个特点:会将队列中的回调函数执行完成之后才只能进行下一步,而nextTick和Promise中回调函数中存在nextTick和Promise,那么它们的回调函数也会在本次被执行。这样有可能造成饥饿陷阱。
结果就是会一直输出nextTick,setTimeout 得不到机会执行。
nextTick和Promise之间是nextTick先于Promise执行
其他几个阶段在后面介绍
参考资料
Node.js 事件循环,定时器和
process.nextTick()
Node.js Event Loop 的理解 Timers,process.nextTick()
The text was updated successfully, but these errors were encountered: