我一直在深入了解 node 的内部 struct .js架构,我经常看到的一个术语是"滴答声",如"事件循环的下一滴答声"或函数nextTick().

我还没有看到"滴答"到底是什么的确切定义.根据各种文章(such as this one篇),我已经能够在脑海中拼凑出一个概念,但我不确定它有多准确.

我能得到一个 node 的精确和详细的描述吗.js事件循环滴答?

推荐答案

请记住,虽然JavaScript是单线程的,但所有 node 的I/O和对本机API的调用要么是异步的(使用特定于平台的机制),要么在单独的线程上运行.(这些都是通过libuv处理的.)

因此,当套接字上有可用数据或本机API函数返回时,我们需要一种同步方式来调用对刚刚发生的特定事件感兴趣的JavaScript函数.

It's not safe to just call the JS function from the thread where the native event happened for the same reasons that you'd encounter in a regular multi-threaded application – race conditions, non-atomic memory access, and so forth.

所以我们要做的是以线程安全的方式将事件放置在队列中.在过于简化的伪代码中,类似于:

lock (queue) {
    queue.push(event);
}

然后,回到主JavaScript thread(但在C端),我们做了如下操作:

while (true) {
    // this is the beginning of a tick

    lock (queue) {
        var tickEvents = copy(queue); // copy the current queue items into thread-local memory
        queue.empty(); // ..and empty out the shared queue
    }

    for (var i = 0; i < tickEvents.length; i++) {
        InvokeJSFunction(tickEvents[i]);
    }

    // this the end of the tick
}

while (true)(实际上并不存在于node的源代码中;这纯粹是说明性的)代表event loop.内部for为队列中的每个事件调用JS函数.

这是一个记号:与任何外部事件关联的零个或多个回调函数的同步调用.一旦队列清空,最后一个函数返回,勾号就结束了.我们回到开头(下一个勾号),判断从其他线程添加到队列中的事件.

什么东西可以添加到队列中?

  • process.nextTick
  • setTimeout/setInterval
  • I/O(来自fsnet等的内容)
  • crypto的处理器密集型功能,如加密流、pbkdf2和PRNG(实际上是…)
  • 使用libuv work queue使同步C/C++库调用看起来是异步的任何本机模块

Node.js相关问答推荐

(0,core_1.default)不是使用@middy/core的lambda处理程序上的函数

Sequelize、postgres和posgis:在n°;公里

为什么 Cors 在 NodeJS 中不起作用

Rest-Api动态图像路径和Express除非

如何从 Mongo Atlas 触发器向 GCP PubSub 发出经过身份验证的请求

无法将示例 Node.js 应用程序部署到 AWS Elastic Beanstalk

具有项目外部子路径导入的 Firebase 函数

未授权使用联合身份未授权用户角色从 Amplify graphQL 访问类型 Y 上的 X

在 getServerSideProps 中使用 EmailProvider 获取 NextAuth 会话会抛出 fs找不到模块

为什么它无法发送发布请求并更改为 chrome 中的获取方法?

nvm / node / npm: node 12 的 npm 比 node 14 的更新?

AWS EC2 npm install 突然很慢

tsc:当我上传 React+next js 和 node 项目时,在 heroku 找不到

NodeJs 过滤掉目录异步

file.slim.js 中的苗条是什么

将 myproject/.npmrc 与注册表一起使用

Sequelize 基于关联的查找

Node.js 连接仅适用于本地主机

node --experimental-modules,请求的模块不提供名为的导出

yarn 和 npm 的主要区别是什么?