29 # node 中的 eventloop

process.cwd

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

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

console.log(process.cwd());

29 # node 中的 eventloop_第1张图片

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

29 # node 中的 eventloop_第2张图片

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

29 # node 中的 eventloop_第3张图片

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

console.log(process.env.kaimo);

29 # node 中的 eventloop_第4张图片

node 中的 eventloop

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

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

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

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

从上至下执行分成下面这些阶段,每个框被称为事件循环机制的一个阶段,这些阶段都是一个队列。
29 # node 中的 eventloop_第5张图片

  • 定时器(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。

29 # node 中的 eventloop_第6张图片

按照上面的概览图,应该先走 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
29 # node 中的 eventloop_第7张图片

process.nextTick

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

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

29 # node 中的 eventloop_第8张图片

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);

29 # node 中的 eventloop_第9张图片

你可能感兴趣的:(前端工程架构,Node,/,Node,框架,node.js,eventloop)