你可能不知道的 15 个 Node.js 高级技巧(实战干货)

你可能不知道的 15 个 Node.js 高级技巧(实战干货)

作为前端开发者,当我们掌握了 Node.js 的基础用法后,如何进一步提升开发效率?本文将分享 15 个你可能不知道的 Node.js 高级技巧,涵盖性能优化、调试技巧、实用 API 和工程化实践,助你成为 Node.js 高手!


一、路径处理:比 path.join 更高效的方式

// 传统方式
const path = require('path');
const fullPath = path.join(__dirname, 'files', 'test.txt');

// 更快的方式(Node.js 14+)
const fullPath2 = `${__dirname}/files/test.txt`;

为什么更快:现代 Node.js 对模板字符串的路径处理做了优化,简单场景下比 path.join 性能更好。


二、util.promisify 的隐藏用法

我们都知道可以用它转换回调函数,但它还能处理自定义的回调模式:

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

// 自定义回调函数(非标准 error-first 格式)
function customCallback(data, callback) {
  callback(null, data.toUpperCase());
}

// 告诉 util.promisify 回调模式
customCallback[util.promisify.custom] = (data) => {
  return new Promise((resolve) => {
    customCallback(data, (err, result) => {
      resolve(result);
    });
  });
};

const promisified = util.promisify(customCallback);

三、内存泄漏检测:--trace-gc 的进阶用法

node --trace-gc --trace-gc-verbose app.js

输出分析

  • 关注 Mark-sweepScavenge 的频率
  • 如果老生代(Old Space)持续增长,可能存在内存泄漏

进阶工具

node --heap-prof app.js # 生成.heapprofile文件

用 Chrome DevTools 的 Memory 面板分析。


四、AsyncLocalStorage 实现全链路追踪

cls-hooked 更现代的解决方案:

const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();

// 中间件示例
app.use((req, res, next) => {
  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set('requestId', uuid());
    next();
  });
});

// 在任何地方获取上下文
function log() {
  const store = asyncLocalStorage.getStore();
  console.log(`[${store.get('requestId')}] Log message`);
}

五、Worker Threads 实战技巧

1. 共享内存的妙用

const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
  const sharedBuffer = new SharedArrayBuffer(4);
  const arr = new Int32Array(sharedBuffer);
  new Worker(__filename, { workerData: sharedBuffer });
} else {
  const arr = new Int32Array(workerData);
  Atomics.add(arr, 0, 1); // 原子操作
}

2. 线程池实现

const { Worker, isMainThread, threadId } = require('worker_threads');

class ThreadPool {
  constructor(size) {
    this.workers = Array(size).fill().map(() => new Worker(__filename));
  }
  
  dispatch(task) {
    const worker = this.workers.find(w => !w.busy);
    worker.busy = true;
    worker.postMessage(task);
    worker.once('message', () => worker.busy = false);
  }
}

六、Buffer 的高阶用法

1. 内存复用池

const bufferPool = [];
function getBuffer(size) {
  const buf = bufferPool.find(b => b.length >= size) || Buffer.allocUnsafe(size);
  return buf.slice(0, size);
}

function releaseBuffer(buf) {
  bufferPool.push(buf);
}

2. 零拷贝转换

const buf = Buffer.from('hello');
const arr = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);

七、process 对象的隐藏功能

1. 实时内存监控

setInterval(() => {
  const mem = process.memoryUsage();
  console.log(`RSS: ${(mem.rss / 1024 / 1024).toFixed(2)} MB`);
}, 1000);

2. 捕获未处理的 Promise 异常

process.on('unhandledRejection', (err) => {
  console.error('有Promise没catch!', err);
  // 可以在这里上报错误
});

八、fs 模块的进阶技巧

1. 递归目录遍历(比 readdir 更快)

const { opendir } = require('fs/promises');

async function scan(dir) {
  const dirHandle = await opendir(dir);
  for await (const dirent of dirHandle) {
    console.log(dirent.name);
  }
}

2. 零拷贝文件发送

const fs = require('fs');
const http = require('http');

http.createServer((req, res) => {
  const stream = fs.createReadStream('bigfile.zip');
  stream.pipe(res); // 零拷贝传输
}).listen(3000);

九、perf_hooks 性能分析

const { performance, PerformanceObserver } = require('perf_hooks');

const obs = new PerformanceObserver((items) => {
  console.log(items.getEntries()[0].duration);
  performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });

performance.mark('start');
// 执行代码...
performance.mark('end');
performance.measure('耗时', 'start', 'end');

十、module 的冷门 API

1. 创建虚拟模块

const { Module } = require('module');
const vm = require('vm');

const mod = new Module('virtual');
mod._compile('exports.hello = "world"', 'virtual.js');
console.log(mod.exports); // { hello: 'world' }

2. 劫持 require

const realRequire = Module.prototype.require;
Module.prototype.require = function(id) {
  if (id === 'axios') {
    return realRequire.call(this, 'axios-mock');
  }
  return realRequire.call(this, id);
};

结语

掌握这些高级技巧后,你的 Node.js 开发水平将提升到一个新的层次。建议:

  1. 在项目中逐步尝试这些技巧
  2. 关注 Node.js 官方博客的更新
  3. 参与开源项目,学习更多实战经验

最后的小测验:你知道 Node.js 中如何实现真正的 Singleton 模式吗?(提示:利用 require 缓存机制)

欢迎在评论区分享你的 Node.js 技巧!如果觉得有用,请点赞收藏支持~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值