深入nodejs的event-loop

此处如无特殊指出的话,event loop的语境都是指nodejs

本文研究所用的nodejs环境是:操作系统window10 + nodejs版本号为v12.16.2

什么是event loop?

event loop是指由libuv提供的,一种实现非阻塞I/O的机制。具体来讲,因为javascript一门single-threaded编程语言,所以nodejs只能把异步I/O操作的实现(非阻塞I/O的实现结果的就是异步I/O)转交给libuv来做。因为I/O既可能发生在很多不同操作系统上(Unix,Linux,Mac OX,Window),又可以分为很多不同类型的I/O(file I/O, Network I/O, DNS I/O,database I/O等)。所以,对于libuv而言,如果当前系统对某种类型的I/O操作提供相应的异步接口的话,那么libuv就使用这些现成的接口,否则的话就启动一个线程池来自己实现。这就是官方文档所说的:“事件循环使Node.js可以通过将操作转移到系统内核中来执行非阻塞I / O操作(尽管JavaScript是单线程的)”的意思。

The event loop is what allows Node.js to perform non-blocking I/O operations — despite the fact that JavaScript is single-threaded — by offloading operations to the system kernel whenever possible.

nodejs的架构

在继续讨论nodejs event loop之前,我们不妨来看看nodejs的架构图:

在这里插入图片描述

从上面的架构图,你可以看出,libuv是位于架构的最底层的。而我们所要讲得event loop的实现是由libuv来提供的。现在,你的脑海里面应该有一幅完整的画面,并清楚地知道event loop到底处在哪个位置了。

这里值得强调的一点是,无论是chrome浏览器中的还是nodejs中的event loop,其实都不是由v8引擎来实现的。

关于event loop几个误解

误解1:event loop和用户代码分别跑在不同的线程上

经常听到这样的说法,用户的javascript代码跑在主线程上,nodejs其余的javascript代码(不是用户写的)跑在event loop的这个线程上。每一次当有异步操作发生的时候,主线程会把I/O操作的实现交给event loop线程。当异步I/O有了结果之后,event loop线程就会把结果通知主线程,主线程就会去执行用户注册的callback函数。

真相

不管是用户写的还是nodejs本身内置的javascript代码(nodejs API),所有的javascript代码都运行在同一个线程里面。在nodejs的角度看来,所有的javascript代码要么是同步代码,要么就是异步代码。或许我们可以这样说,所有的同步代码的执行都是由v8来完成的,所有异步代码的执行都是由libuv提供的event loop功能模块来完成的。那event loop与v8是什么关系呢?我们可以看看下面的源代码:

Environment* CreateEnvironment(Isolate* isolate, uv_loop_t* loop, Handle<Context> context, int argc, const char* const* argv, int exec_argc, const char* const* exec_argv) {
   
  HandleScope handle_scope(isolate);

  Context::Scope context_scope(context);
  Environment* env = Environment::New(context, loop);

  isolate->SetAutorunMicrotasks(false);

  uv_check_init(env->event_loop(), env->immediate_check_handle());
  uv_unref(reinterpret_cast<uv_handle_t*>(env->immediate_check_handle()));
  uv_idle_init(env->event_loop(), env->immediate_idle_handle());
  uv_prepare_init(env->event_loop(), env->idle_prepare_handle());
  uv_check_init(env->
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值