NodeJs

Node.js 使用 CommonJS 模块系统(v12以上也支持ESM),而在浏览器使用 ESM 标准。
这意味着在 Node.js(包括webpack) 中使用 require(),而在浏览器中则使用 import。
NodeJs和Chrome中的JS均基于V8引擎,NodeJs甚至可以开发桌面应用(如electron开发的VSCode和WhatsApp)。

环境变量

process 模块提供了 env 属性,该属性承载了在启动进程时设置的所有环境变量。

process.env.NODE_ENV // 默认为"development"

从命令行获取参数

node app.js A B

//app.js
process.argv.forEach((val, index) => {
  console.log(`${index}: ${val}`)
})

//log
0: C:\Program Files\nodejs\node.exe
1: C:\Users\62406\Desktop\other\node\node.js
2: A
3: B

当文件发生改动时自动重启应用

node --watch app.js

命令行模式

在命令行中输入node进入node环境REPL模式。

  • .editor:允许输入多行
  • .load:加载 JavaScript 文件
  • .save:将你在 REPL 会话中输入的所有内容保存到文件(指定文件名)
接受来自命令行的输入
const readline = require('node:readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.question(`What's your name?`, name => {
  console.log(`Hi ${name}!`);
  rl.close();
});

util.promisify

内置方法,将基于回调的函数转换为 Promise 函数。

class MyClass {
  myCallbackFn(cb) {
    cb(null, this)
  }
}

const obj = new MyClass()

// 为保留上下文(使 this 指向不变),因为 promisified 是 obj 的属性
obj.promisified = require('util').promisify(obj.myCallbackFn)

const context = await obj.promisified()
console.log(context === obj) // true

事件

通过events模块构建了类似浏览器中的事件系统

const EventEmitter = require('events')
const eventEmitter = new EventEmitter()
eventEmitter.on('start', number => {
  console.log(`开始 ${number}`)
})

eventEmitter.emit('start', 23)
  • once(): 添加单次监听器。
  • removeListener() / off(): 从事件中移除事件监听器。
  • removeAllListeners(): 移除事件的所有监听器。

路径

使用path模块管理路径

const path = require('node:path');

const notes = '/users/joe/notes.txt';

path.dirname(notes); // /users/joe
path.basename(notes); // notes.txt
path.extname(notes); // .txt
  • 使用 path.join() 连接路径的两个或多个部分:
const name = 'joe';
path.join('/', 'users', name, 'notes.txt'); // '/users/joe/notes.txt'
  • 使用 path.resolve() 将相对路径加入到当前工作目录:
path.resolve('tmp', 'joe.txt'); // '/Users/joe/tmp/joe.txt' if run from my home folder

文件

文件读写:
  1. fs.open + fs.read(write),手动操作读写,优点是可以控制每次读取的位置和量:
const fs = require('fs');
fs.open('file.txt', 'r', (err, fd) => {
  if (err) throw err;
  const buffer = Buffer.alloc(1024);
  fs.read(fd, buffer, 0, buffer.length, 0, (err, bytesRead) => {
    if (err) throw err;
    console.log(buffer.toString('utf8', 0, bytesRead));
    fs.close(fd, (err) => { if (err) throw err; });
  });
});
  1. fs.readFile(writeFile),一次性读取整个文件,但对大文件内存占用较多:
const fs = require('fs');
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});
  1. (推荐)fs.createReadStream(createWriteStream),流式处理,内存占用极少(分块读取),还方便管道传输到其他流(HTTP响应、压缩流等):
// 现代推荐组合:流 + 异步迭代
const fs = require('fs');
async function processLargeFile() {
  const stream = fs.createReadStream('massive.csv');
  let lineCount = 0;
  
  for await (const chunk of stream) {
    lineCount += chunk.toString().split('\n').length - 1;
  }
  
  console.log(`Total lines: ${lineCount}`);
}

以上方法都有其同步版本,如fs.openSyncfs.readFileSync
在Node14+版本还可以使用fs/promises模块下的Promise版本:

const fs = require('node:fs/promises');
// Or const fs = require('fs').promises before v14.
async function example() {
  let filehandle;
  try {
    filehandle = await fs.open('/Users/joe/test.txt', 'r');
    console.log(filehandle.fd);
    console.log(await filehandle.readFile({ encoding: 'utf8' }));
  } finally {
    if (filehandle) await filehandle.close();
  }
}
example();

老版本可以用util.promisify转化出 Promise 版本:

const fs = require('node:fs');
const util = require('node:util');

async function example() {
  const open = util.promisify(fs.open);
  const fd = await open('/Users/joe/test.txt', 'r');
}
example();
其他文件操作方法
  • fs.stat 获取文件/目录信息
  • fs.access 判断文件/目录是否存在
  • fs.copyFile 复制文件
  • fs.mkdir 创建目录
  • fs.readdir 读取目录内容
  • fs.unlink 删除文件/目录
  • fs.rename 重命名文件/目录
fs.open的几种模式
模式  描述
r   读取(默认),文件不存在则报错,指针在开头
r+  读写,文件不存在则报错,指针在开头
w   写入,文件不存在则创建,存在则清空,指针在开头
w+  读写,文件不存在则创建,存在则清空,指针在开头
a   追加写入,文件不存在则创建,指针在末尾
a+  读取和追加写入,文件不存在则创建,指针在末尾

测试

在项目中创建.test.js后缀文件,并通过node --test即可自动搜索并运行

const { test, describe } = require('node:test');
const assert = require('node:assert/strict');

// 简单测试用例
test('同步测试示例', (t) => {
  assert.equal(1, 1);
});

// 异步测试
test('异步测试示例', async (t) => {
  const result = await someAsyncFunction();
  assert.ok(result);
});
  • 检查测试代码覆盖率
node --experimental-test-coverage --test main.test.js
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容