当前位置: 首页 > news >正文

Node.js 中常用的异步函数讲解、如何检测异步操作时间和事件

✅ 1. process.nextTick()

功能:

process.nextTick() 用于将一个回调函数添加到当前阶段执行完后事件循环的下一轮开始前执行的队列中。

特点:

  • 优先级高于所有微任务(包括 Promise.then

  • 属于 Node.js 独有,不适用于浏览器

示例代码:

console.log('start');process.nextTick(() => {console.log('nextTick');
});Promise.resolve().then(() => {console.log('promise');
});console.log('end');

输出:

start
end
nextTick
promise

✅ 2. Promise.resolve().then(...)

功能:

Promise.then() 是 JavaScript 中的微任务机制之一,在本轮事件循环的所有同步代码执行完毕后立即执行

示例代码:

console.log('start');Promise.resolve().then(() => {console.log('promise');
});console.log('end');

输出:

start
end
promise

✅ 3. setTimeout(fn, delay)

功能:

将回调函数放入宏任务队列,在最少等待 delay 毫秒后执行(并不是精准时间,受事件循环调度影响)。

示例代码:

console.log('start');setTimeout(() => {console.log('timeout');
}, 0);console.log('end');

输出:

start
end
timeout

✅ 4. setInterval(fn, delay)

功能:

每隔 delay 毫秒重复执行一次函数。

特点:

  • 需要与 clearInterval() 搭配使用,防止无限循环或内存泄漏

示例代码:

let count = 0;
const timer = setInterval(() => {console.log('interval', count++);if (count > 2) clearInterval(timer);
}, 1000);

输出(每秒打印一次):

interval 0
interval 1
interval 2

✅ 5. clearTimeout(timeoutID)

功能:

取消之前由 setTimeout() 注册的定时器。

示例代码:

const timer = setTimeout(() => {console.log('should not run');
}, 1000);clearTimeout(timer);

输出:

不会有任何输出,因为定时器被取消了。


✅ 6. clearInterval(intervalID)

功能:

取消由 setInterval() 注册的循环任务。

示例代码:

let count = 0;
const id = setInterval(() => {console.log('interval', count++);if (count === 3) clearInterval(id);
}, 500);

🧠 拓展:其他常用异步任务

setImmediate(callback)

  • Node.js 独有。

  • 当前事件循环结束后立即执行,优先级比 setTimeout(..., 0) 更高。

setImmediate(() => console.log('setImmediate'));
setTimeout(() => console.log('setTimeout'), 0);

输出顺序视 Node 版本而定,setImmediate 通常优先。


🔁 执行优先级总结(Node.js):

同步代码 > process.nextTick > Promise.then > setTimeout/setInterval/setImmediate

✅ 实战演示对比:

console.log('start');process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('promise'));
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));console.log('end');

常见输出(Node.js v16+):

start
end
nextTick
promise
timeout
immediate

二、NodeJS如何监测异步操作的事件

在 Node.js 中,“异步操作”涉及到很多事件的注册与触发,而 监测异步操作的事件流转过程 对调试、排查内存泄漏、分析性能瓶颈等非常重要。Node.js 提供了多种方式可以 监测异步操作的生命周期与事件行为


🧩 1. 使用 async_hooks 模块(核心方案)

Node.js 从 v8.1.0 开始提供了 async_hooks 模块,用于跟踪异步资源的生命周期(Promise、setTimeout、fs、net 请求等)。

✅ 示例:追踪异步操作

const async_hooks = require('async_hooks');
const fs = require('fs');const hook = async_hooks.createHook({init(asyncId, type, triggerAsyncId, resource) {fs.writeSync(1, `[init] id: ${asyncId}, type: ${type}, trigger: ${triggerAsyncId}\n`);},before(asyncId) {fs.writeSync(1, `[before] id: ${asyncId}\n`);},after(asyncId) {fs.writeSync(1, `[after] id: ${asyncId}\n`);},destroy(asyncId) {fs.writeSync(1, `[destroy] id: ${asyncId}\n`);}
});hook.enable();setTimeout(() => {console.log('setTimeout done');
}, 100);

💡 输出示例:

[init] id: 6, type: Timeout, trigger: 1
[before] id: 6
setTimeout done
[after] id: 6
[destroy] id: 6

你可以看到异步资源从创建到销毁全过程。


🧪 2. 使用 perf_hooks 监控异步性能

perf_hooks 模块可以记录函数执行时间,适合性能调试:

const { performance, PerformanceObserver } = require('perf_hooks');performance.mark('start');setTimeout(() => {performance.mark('end');performance.measure('timeout duration', 'start', 'end');
}, 100);const obs = new PerformanceObserver((items) => {console.log(items.getEntries());
});obs.observe({ entryTypes: ['measure'] });

🕵️ 3. 使用 EventEmitter 自定义事件监测

Node 中很多异步库(如 httpfsnet)都继承自 EventEmitter,你可以自己监听事件触发:

const fs = require('fs');const stream = fs.createReadStream('./some.txt');stream.on('open', () => {console.log('stream opened');
});stream.on('data', (chunk) => {console.log(`chunk received: ${chunk.length} bytes`);
});stream.on('end', () => {console.log('stream ended');
});

🔍 4. 使用 APM 工具或监控平台

如果你做的是生产级应用,建议配合专业工具做异步事件监测:

  • Node Clinic:由 NearForm 开源的诊断工具

  • Elastic APM / New Relic / Datadog:可监控事件调用链、异步瓶颈

  • Chrome DevTools / VSCode:可远程调试 node --inspect


🧠 总结:不同监测方案对比

方式功能场景
async_hooks精确追踪所有异步资源生命周期调试复杂异步流程
perf_hooks性能度量和函数执行时间统计性能分析
EventEmitter捕捉异步事件本身(如 on(data), on(end))I/O 事件处理观察
DevTools / APM 工具图形化追踪调用栈生产监控、性能排查


是否需要我 结合一个实际的 Node 项目,演示如何用 async_hooks 追踪数据库、定时任务和网络请求的执行流?还是要我帮你分析你自己的项目异步流程?

三、NodeJS如何监测异步操作的时间

在 Node.js 中,监测异步操作的执行时间 是性能调优的常见需求,特别是在处理数据库查询、API 请求、文件操作等耗时操作时。下面是几种实用的方法,涵盖了从简单代码计时到底层异步性能钩子的全面方案。


✅ 方法一:使用 console.time() / console.timeEnd()(适合快速调试)

console.time('timer');setTimeout(() => {console.timeEnd('timer'); // 输出:timer: 100.123ms(示例)
}, 100);

优点:快速、轻便、零依赖
缺点:无法穿透异步调用链


✅ 方法二:使用 performancePerformanceObserver(推荐,适合结构化统计)

Node.js 提供的 perf_hooks 模块是内置性能监控工具。

const { performance, PerformanceObserver } = require('perf_hooks');performance.mark('start');setTimeout(() => {performance.mark('end');performance.measure('timeout_duration', 'start', 'end');
}, 100);const obs = new PerformanceObserver((items) => {console.log(items.getEntries()[0]); // { name: 'timeout_duration', duration: 100.xxx, ... }
});obs.observe({ entryTypes: ['measure'], buffered: true });

优势

  • 可标记多个时间点

  • 用于构建 Web 性能指标收集工具

  • 结构化输出,可聚合分析


✅ 方法三:使用 async_hooks 配合 executionAsyncId(适合深度追踪异步任务)

const async_hooks = require('async_hooks');
const { performance } = require('perf_hooks');const timings = new Map();const hook = async_hooks.createHook({init(asyncId, type, triggerAsyncId) {timings.set(asyncId, performance.now());},destroy(asyncId) {const start = timings.get(asyncId);if (start) {const duration = performance.now() - start;console.log(`[${asyncId}] async duration: ${duration.toFixed(2)} ms`);timings.delete(asyncId);}}
});hook.enable();// 异步操作
setTimeout(() => {console.log('setTimeout done');
}, 200);

注意:不要用 console.log 打印钩子内部内容,容易导致无限递归,用 fs.writeSync 更安全。


✅ 方法四:使用第三方库(可选)

工具库用途
newrelic / datadog / Elastic APM生产监控,链路追踪
node-clinicNearForm 出品,性能分析神器
why-is-node-running找出未结束的异步任务


✅ 方法五:手动嵌套 Date.now() 统计执行时长(最低成本方案)

const start = Date.now();fs.readFile('./test.txt', 'utf8', (err, data) => {const duration = Date.now() - start;console.log(`readFile took ${duration}ms`);
});

🧠 总结对比

方法精度易用性场景
console.time()毫秒级⭐⭐⭐⭐快速调试
performance + measure微秒级⭐⭐⭐正式代码推荐
async_hooks + Map微秒级⭐⭐全链路异步追踪
手动 Date.now()毫秒级⭐⭐⭐小型代码段
第三方 APM 工具微秒~ms⭐⭐企业级、生产环境监控


如果你想在自己的项目中实战一遍,比如:统计一次 HTTP 请求或数据库操作的精确耗时,并记录日志,我可以帮你写一个完整中间件或者封装工具函数,是否需要?

http://www.xdnf.cn/news/1044127.html

相关文章:

  • NodeJS的yarn和npm作用和区别,为什么建议用yarn
  • AWS 解决方案深度剖析:Amazon QLDB — 构建可信赖、不可变的数据审计基石
  • 智造奇点:AI超级工厂如何重塑制造业DNA
  • nodejs和npm升级
  • 什么是稳定币?
  • windows制作ubuntu系统安装盘
  • 算法题(169):最大子段和(分治思想)
  • AnimateCC及CreateJS:打飞机的4版本V1、V2、V3、V4
  • UltraISO绿色便携版v9 下载与安装教程
  • 基于51单片机的校园打铃及灯控制系统
  • 芯片测试之 trim修调详解
  • 《棒垒球科普》足垒球的规则·垒球2号位
  • [直播推流] 使用 librtmp 库推流
  • KSP密钥管理系统赋能智能制造:密钥管理系统在智能制造行业中有哪些典型应用
  • 单机定时任务@Schedule的常见问题
  • 5.5.1_哈夫曼树
  • uni-app项目loading显示方案
  • neo4j社区版数据库下载安装
  • 玛哈特纵剪矫平机:金属板材精密加工的“开平裁切”核心装备
  • SEO关键词与长尾词布局实战
  • 解决国内无法加载谷歌验证码(reCAPTCHA):URL 重定向配置指南
  • github-mcp-server v0.5.0 发布详解:远程 GitHub MCP 服务器全新升级与最佳实践
  • 【专业数据库探索 05】ArangoDB多模数据库革命:一个数据库解决文档图关系三大数据模型
  • Qwen3 Embedding 测试
  • 8. TypeScript 类
  • Lambda 表达式的语法与使用:更简洁、更灵活的函数式编程!
  • Dina靶机渗透
  • 算法训练第十七天
  • CQF预备知识:Python相关库 -- 通用非均匀随机数抽样 scipy.stats
  • 关于allegro 导入网表报错:Unable to find pin name in问题的解决