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