Node.js异步回调中performance.now()赋值变量为何为undefined?
异步回调变量未赋值的成因分析及解决办法
成因解释
你遇到的st2、st3、st4输出为undefined的问题,本质是Node.js异步I/O的执行顺序导致的,和performance.now()本身无关:
- 同步代码优先执行:Node.js会先跑完所有同步代码——从
st1赋值开始,到console.log("end")、st5赋值,最后执行打印变量的console.log语句。此时所有readFile、writeFile的异步回调都还没触发,st2、st3、st4还是初始声明时的undefined。 - 异步回调后执行:只有当Node.js的事件循环处理完文件I/O的任务时,才会依次调用嵌套的异步回调函数,这时候才会给
st2、st3、st4赋值,但这个时机已经晚于你打印变量的操作了。
从你的运行结果顺序也能验证这一点:同步代码的start、middle、end、after end以及变量打印先输出,之后才是异步回调里的undefined(writeFile的回调参数result本身就是undefined)和after result。
解决办法
要正确获取所有时间变量的值,需要保证打印操作在所有异步回调执行完成后触发,有两种常用方式:
方式1:将打印逻辑移到最内层异步回调
把变量打印代码放到writeFile的回调函数末尾,确保所有异步操作完成后再执行:
const { performance } = require("perf_hooks"); var st1 = performance.now(); console.log("start"); var st2, st3, st4, st5; const { readFile, writeFile } = require("fs"); console.log("middle"); readFile("./content/first.txt", "utf-8", (err, result) => { if (err) { console.log(err); return; } const first = result; st2 = performance.now(); readFile("./content/second.txt", "utf-8", (err, result) => { if (err) { console.log(err); return; } const second = result; st3 = performance.now(); writeFile( "./content/result-async.text", `Here is the result : ${first}: ${second}`, (err, result) => { if (err) { console.log(err); return; } console.log(result); console.log("after result"); st4 = performance.now(); st5 = performance.now(); // 所有异步操作完成后再打印 console.log(`st1=${st1},st2=${st2},st3=${st3},st4=${st4},st5=${st5}`); } ); }); }); console.log("end"); console.log("after end");
方式2:使用Promise/async-await简化异步流程
利用Node.js提供的promise版fs方法,通过async-await让异步代码逻辑更清晰,同时确保顺序执行:
const { performance } = require("perf_hooks"); // 引入promise版本的fs方法 const { readFile, writeFile } = require("fs").promises; async function measureAsyncTime() { const st1 = performance.now(); console.log("start"); console.log("middle"); try { // 等待第一个文件读取完成 const first = await readFile("./content/first.txt", "utf-8"); const st2 = performance.now(); // 等待第二个文件读取完成 const second = await readFile("./content/second.txt", "utf-8"); const st3 = performance.now(); // 等待文件写入完成 await writeFile( "./content/result-async.text", `Here is the result : ${first}: ${second}` ); const st4 = performance.now(); const st5 = performance.now(); // 所有异步操作完成后打印时间 console.log(`st1=${st1},st2=${st2},st3=${st3},st4=${st4},st5=${st5}`); console.log("after result"); } catch (err) { console.error(err); } } measureAsyncTime(); console.log("end");
内容的提问来源于stack exchange,提问作者blueflyer
相关产品推荐
相关产品推荐

