29 # node 中的 eventloop

简介: 29 # node 中的 eventloop

process.cwd

cwd:current working directory 表示当前用户的工作目录(这个目录可以更改用户自己切换即可)

当用户在哪执行 node 命令,就去哪找配置文件

console.log(process.cwd());

__dirname:表示当前文件所在的目录,这个目录是不能手动修改的,它不是 global 上的属性,是每个模块都会传入的属性

process.env

env:环境变量,可以根据环境变量实现不同的功能,比如:

let domain = process.env.NODE_ENV === "production" ? "localhost" : "https://blog.csdn.net/kaimo313";

设置临时的环境变量:

  • windows:set key=value
  • mac:export key=value

我的系统是 windows 的,下面我用 set key=value 试一下

先在 cmd 里设置临时的环境变量,set kaimo=313,然后执行 node env.js,输出是有 313 的值

set kaimo=313

然后你打开 powershell 执行 node env.js 是没有这个值输出

console.log(process.env.kaimo);

node 中的 eventloop

事件循环是 Node.js 处理非阻塞 I/O 操作的机制。

现在浏览器的事件环跟 node 的事件环执行效果是一样的(node 10 版本后)

详细的可以查看文档:https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick

事件循环操作顺序的简化概览图:

从上至下执行分成下面这些阶段,每个框被称为事件循环机制的一个阶段,这些阶段都是一个队列。

  • 定时器(timers):此阶段执行由 setTimeout()setInterval() 排序。
  • 挂起的回调函数(pending callbacks):执行 I/O 回调推迟到下一个循环迭代。【内部机制】
  • idle, prepare:仅在内部使用。【内部机制】
  • 轮询(poll):检索新的 I/O 事件; 执行与 I/O 相关的几乎任何回调(由“计时器”或 “setImmediate()”所设的紧邻回调除外); node 将在适当时机在此处暂停。
  • 检查阶段(check):setImmediate() 回调在此处被调用。
  • 关闭的回调函数(close callbacks):一些关闭的回调函数,如:socket.on('close', ...)

setImmediate vs setTimeout

  • setImmediate() 实际上是一个在事件循环的单独阶段运行的特殊计时器。它使用一个 libuv API 来安排回调在轮询阶段完成后执行。。
  • setTimeout() 在已过期的最小阈值后运行。
setTimeout(() => {
    console.log("setTimeout");
}, 0);
setImmediate(() => {
    console.log("setImmediate");
});

上面代码有时先输出 setTimeout,然后输出 setImmediate,有时先输出 setImmediate,再输出 setTimeout。

按照上面的概览图,应该先走 timers 再到 check 阶段,先输出 setTimeout,然后输出 setImmediate,那为什么会出现有时反过来的情形?

这是因为如果运行不在 I/O 周期(即主模块)内的脚本,则执行两个计时器的顺序是非确定性的,因为它受进程性能的约束。进入事件环时 setTimeout 有可能没有完成。

我们可以试试放在 I/O 周期 里:

// poll -> check -> timers
const fs = require("fs");
fs.readFile("./file/name.txt", "utf-8", (err, data) => {
    if (err) throw err;
    console.log(data);
    setTimeout(() => {
        console.log("setTimeout");
    }, 0);
    setImmediate(() => {
        console.log("setImmediate");
    });
});

这个顺序就是一个确定的 poll -> check -> timers

process.nextTick

node 中自己实现的微任务 process.nextTick / queueMicrotask,宏任务 setImmediate

setTimeout(() => {
    console.log(2);
});
process.nextTick(() => {
    console.log(1);
});
queueMicrotask(() => {
    console.log(3);
});
// 输出 1 3 2

process.nextTick 并不属于事件环的一部分,在本轮代码执行后执行(timers 到 poll 为一轮,如果后有 check 就执行 check )

// nextTick 比 Promise 的 then 要快一些
setTimeout(() => {
    console.log(1);
    Promise.resolve().then(() => {
        console.log("then");
    });
    process.nextTick(() => {
        console.log("nextTick");
    });
}, 0);
setTimeout(() => {
    console.log(2);
}, 0);

目录
相关文章
|
22天前
|
存储 JavaScript 前端开发
Node 中的 AsyncLocalStorage 的前世今生和未来(一)
作者系统详实的介绍了什么是AsyncLocalStorage、如何使用、Node 是如何实现的 AsyncHook等。不论你是0基础还是对此API有些了解的读者都比较适合阅读此文。(文末有活动)
|
22天前
|
JavaScript 前端开发 数据库
【Node系列】node中的函数
在Node.js中,函数是一段可重复使用的代码,它可以接受输入(参数),执行一系列操作,并返回一个结果(返回值)。
19 3
|
22天前
|
Web App开发 监控 JavaScript
【Node系列】Node全局对象
global:全局对象,在所有模块中都可以访问
23 1
|
12月前
|
Web App开发 运维 JavaScript
Node的介绍
Node的介绍
131 0
|
缓存 前端开发 JavaScript
Node 案发现场揭秘
Node 案发现场揭秘
|
JSON 负载均衡 JavaScript
Node【一】初识Node
Node【一】初识Node
117 0
Node【一】初识Node
|
消息中间件 JavaScript Shell
Node 进程
在操作系统中,对进程的解释:进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。 - 是应用程序的一次运行过程(动态概念) - 是系统分配和调度资源的基本单位(进程是一般由程序、数据集合和进程控制块三部分组成) - 每个进程有自己独立的空间地址,数据栈(各进程间数据不共享,可通过其他方式进行通信)进程一般有初始态,执行态,等待状态,就绪状态,终止状态五种状态
85 0
|
运维 监控 JavaScript
gmailWatcher之node
gmailWatcher之node
68 0
|
Web App开发 JavaScript 前端开发
node初探 什么是node
前言里面说了,node 是一门使用chorme V8 引擎来解析JavaScript, 并且解决异步IO,事件驱动,高性能的一种脚本语言,它的出来就搭上了chrome浏览器开发的v8引擎的这一趟快车。
node初探 什么是node
|
JavaScript 前端开发 内存技术
Node(一)初识
Node(一)初识
86 0