核心API
全局对象
global
在浏览器全局定义变量会使用window,在Nodejs
中会有一些差异,使用global
作为全局对象。 在ECMAScript2020
为了消除差异化,统一了新的全局关键字globalThis
,所以global === globalThis
。
Nodejs
环境中globalThis
会切换成global
- 在浏览器会被切换为
window
__dirname & __filename
Nodejs
使用的CommonJS
规范,会将模块封装为一个函数,在这个函数里,会传递__dirname
和__filename
这两个参数
__dirname
表示当前模块的所在目录的绝对路径。__filename
表示当前模块的所在文件的绝对路径。
require
封装模块函数传递来的参数,用于引入加载模块。
module
封装模块函数传递来的参数,用于对外输出接口。
更多对象
- Date
- Promise
- Buffer
- setTimeout
- setImmediate
- setInterval
- fetch
- Math
- console
常用内置模块
path
类UNIX
系统遵循POSIX
标准,而Windows
只有部分实现。这就导致不同系统之间的差异化。当一套代码在不同的平台系统运行时,路径的兼容问题难以得到解决。
在Nodejs
中封装好了这么一套API
,屏蔽了这些差异,我们只需要关注模块中的API
的用法即可。
路径信息
basename:返回文件名的最后部分,一般是文件名
jsconst { resolve, basename } = require("path"); const filepath = resolve(__dirname, `../data/data.json`); console.log(basename(filepath)); // data.json
dirname:返回文件中目录的部分
jsconst { resolve, dirname } = require("path"); const filepath = resolve(__dirname, `../data/data.json`); console.log(dirname(filepath)); // /Users/xxx/codes/node/src/data
extname:返回文件的扩展名
jsconst { resolve, extname } = require("path"); const filepath = resolve(__dirname, `../data/data.json`); console.log(extname(filepath)); // .json
序列化
parse、format:将文件路径序列化成一个对象或者将对象序列化为路径
jsconst { resolve, parse ,format} = require("path"); const filepath = resolve(__dirname, `../data/data.json`); const parseStr = parse(filepath) const formatStr = format(parseStr) console.log(parseStr); console.log(formatStr) // /Users/xxx/codes/node/src/data/data.json // { // root: '/', // dir: '/Users/xxx/codes/node/src/data', // base: 'data.json', // ext: '.json', // name: 'data' // }
isAbsolute:判断文件是否为绝对路径
const { resolve, isAbsolute } = require("path");
const filepath = resolve(__dirname, `../data/data.json`);
console.log(isAbsolute(filepath)) // true
console.log(isAbsolute('../data/data.json')) // false
拼接
join:根据传递的参数,从左到右拼接起来,遇到相对地址,会先拼接再运算地址。
jsconst { join } = require("path"); console.log(join("/data", "../Users/xxx/codes/node/src", "data.json")); // /Users/xxx/codes/node/src/data.json
resolve:
- 从右到左处理传入的路径片段,直到构造出一个绝对路径。
- 如果处理完所有路径片段后仍未生成绝对路径,则会将当前工作目录作为起点。
- 遇到绝对路径时,构造过程会从该绝对路径开始,忽略其左边的所有路径片段。
jsconst { resolve } = require("path"); console.log(resolve("./data", "../Users/xxx/codes/node/src", "data.json")); // /Users/xxx/codes/node/Users/xxx/codes/node/src/data.json console.log(resolve("../data", "data.json")); // /Users/xxx/codes/data/data.json
event
事件触发器,是一个EventEmitter
类,原理是采用了发布订阅设计模式
。Publisher
发布者和Subscriber
订阅者并不直接联系,当一个发布者有新消息时,就将这个消息发布到调度中心。调度中心就会将这个消息通知给所有订阅者。
Nodejs
中的事件对象都是 EventEmitter
对象的实例,是事件管理的通用机制,在 Nodejs
中多数模块都继承了事件,如 fs、http 、stream
。
事件触发器常用的方法:
- on:将监听的事件加入到监听器数组的末尾
- addListener:实际上是
on
方法的别名 - emit:按注册顺序同步地调用为名为
eventName
的事件注册的每个监听器,并将提供的参数传给每个监听器。 - removeListener:移除监听事件
- off:实际上是
removeListener
方法的别名 - removeAllListeners:移除所有监听事件
- once:添加一次性的监听事件,在下次触发时,会先移除再触发此监听器
- newListener:事件,用
on
或addListener
,在添加新监听器时触发 - removeListener:同
newListener
事件,在删除现有监听器时触发
基本使用
我们可以注册多个事件监听,并在合适的时机触发这些事件:
const EventEmitter = require("node:events");
const fs = require("node:fs");
const path = require("node:path");
const eventEmitter = new EventEmitter();
const filePath = path.resolve(__dirname, "../data/data.json");
// 监听事件处理函数
const listener = (type) => {
console.log(`listener: ${type}`);
};
// 监听事件 on | addEventListener
eventEmitter.on("read", listener);
// 监听一次事件
eventEmitter.once("once", listener);
fs.readFile(filePath, (err, data) => {
if (err) {
console.log(err);
return;
}
eventEmitter.emit("once", "once");
// 触发事件,并传递数据
eventEmitter.emit("read", "read");
setTimeout(() => {
// 取消监听 off | removeListener,需要指定事件名和监听器处理事件
eventEmitter.off("read", listener);
}, 1000);
});
如果多个事件被添加到监听队列中,取消监听时,将会取消最近的那次监听,比如下面的🌰:
// 监听事件处理函数
const listener = (type) => {
console.log(`listener: ${type}`);
};
// 监听一次事件
ee.once("read", listener);
// 监听事件
ee.on("read", listener);
// 取消监听
// ee.off("read", listener);
ee.emit("read", "read");
分别是取消监听和不取消监听的表现
自定义事件
通过继承EventEmitter
类,可以对象拥有事件触发器的能力
下面的 🌰 ,每次实例化对象都会触发一个监听器事件:
const EventEmitter = require("node:events");
class Person extends EventEmitter {
constructor(name) {
super();
super.on("new", () => {
console.log(`this class will be created by ${name}`);
});
this.name = name;
super.emit("new", name);
}
}
const lili = new Person("lili");
const lilei = new Person("lilei");
TIP
Nodejs
中很多的API
都是由事件触发器去协助完成的,比如文件流Stream
,http
模块等。
process
获取 进程运行时信息 并控制 进程行为。是Nodejs
操作当前进程和控制当前进程的API
,并挂载到全局下。
高频 API
API | 用途 |
---|---|
process.arch | 返回操作系统的CPU 架构 |
process.cwd() | 返回当前工作目录 |
process.argv | 获取执行进程后的参数,返回一个数组,比如node --help ,会返回--help |
process.memoryUsage() | 获取当前进程的内存情况 |
process.exit(code) | 强制终止进程(code=0表示成功退出) |
process.kill(pid) | 杀死一个指定的进程 |
process.env() | 读取、设置环境变量,在Windows 系统下调用SET 命令,在macos 下则是调用export 命令设置环境变量 |
其他模块
模块 | 功能 | 关键API | 用途 |
---|---|---|---|
os | 操作系统信息 | os.cpus() | 获取CPU核心数 |
os.networkInterfaces() | 获取网络信息 | ||
os.platform() | 返回标识为其编译 Node.js 二进制文件的操作系统平台的字符串。(返回值darwin:macos,win32:windows,其他:Linux) | ||
util | 内置工具函数 | util.promisify() | Nodejs大多数API遵循回调函数的方式,该API可以将回调转为Promise的形式。返回Promise |
util.callbackify() | 与promisify正好反过来,将一个Promise转为回调的形式。 | ||
util.format() | 格式化输出语句。 | ||
console | 控制台输出 | console.log(...args) | 控制台标准输出语句 |
console.table(...args) | 表格化打印对象 |
模拟promisify实现
// 1.promisify 接受一个函数作为参数,返回一个新的函数
const myPromisify = (originalFn) => {
return (...args) => {
// 2. 新的函数会返回一个Promise
return new Promise((resolve, reject) => {
// 3. 在Promise中调用原函数,并将resolve和reject作为参数传入
originalFn(...args, (err, ...values) => {
if (err) {
reject(err);
}
// 4.存在多个结果时,迭代返回,否则直接返回values
if (values && values.length > 1) {
let obj = {};
for (let key in values) {
obj[key] = values[key];
}
resolve(obj);
} else {
resolve(values[0]);
}
});
});
};
};
const execPromise = myPromisify(exec);
async function fn() {
const data = await execPromise("node -v");
console.log(data);
}
fn();