为何调用costCalculator函数先输出undefined?不符合预期
问题:costCalculator函数执行时先输出undefined的原因及解决方法
我编写了如下用于计算员工成本的costCalculator函数:
/** * This function calculates the cost of an employee based on the data in its file * @param {string} filePath - path to the employee data file * @returns {{name: string, cost: number}} - the name and cost of the employee */ function costCalculator(filePath) { const fs = require("fs"); fs.readFile(`${filePath}`,"utf8",(err,data)=>{ if(err){ console.error(err); return; } var employee=JSON.parse(data); let cph=employee["salary"]/employee["hours"]; var result={name:employee["name"],cost:cph}; console.log(result); }); }
执行console.log(costCalculator('mohamed.json'));时,控制台输出:
undefined { name: 'Mohamed', cost: 62.5 }
但期望仅输出:
{ name: 'Mohamed', cost: 62.5 }
原因分析
costCalculator函数内部用了异步的fs.readFile,但函数本身没有任何return语句,JS中函数默认返回undefined。- 调用时用
console.log(costCalculator(...))会先打印函数的返回值undefined;等异步文件读取完成后,才会执行回调里的console.log(result),所以出现两次输出。
解决方案
方案1:最简单的修改——去掉外层的console.log
直接调用函数,不要用console.log包裹:
costCalculator('mohamed.json');
这样函数返回的undefined不会被打印,只有回调里的结果会输出。
方案2:改用Promise+async/await(现代JS推荐写法)
把异步操作包装成Promise,让函数返回结果,调用时用await等待:
const fs = require("fs").promises; // 使用Promise版的fs模块 /** * This function calculates the cost of an employee based on the data in its file * @param {string} filePath - path to the employee data file * @returns {Promise<{name: string, cost: number}>} - the name and cost of the employee */ async function costCalculator(filePath) { try { const data = await fs.readFile(filePath, "utf8"); const employee = JSON.parse(data); const cph = employee.salary / employee.hours; return { name: employee.name, cost: cph }; } catch (err) { console.error(err); throw err; // 可根据需求选择是否抛出错误 } } // 调用时用async函数包裹 (async () => { const result = await costCalculator('mohamed.json'); console.log(result); })();
方案3:保留回调模式,让函数支持外部回调
给函数添加回调参数,把结果交给调用方处理,避免在函数内部打印:
/** * This function calculates the cost of an employee based on the data in its file * @param {string} filePath - path to the employee data file * @param {function(Error?, {name: string, cost: number}?)} callback - 处理结果的回调函数 */ function costCalculator(filePath, callback) { const fs = require("fs"); fs.readFile(filePath, "utf8", (err, data) => { if (err) { console.error(err); callback(err); return; } const employee = JSON.parse(data); const cph = employee.salary / employee.hours; const result = { name: employee.name, cost: cph }; callback(null, result); }); } // 调用方式 costCalculator('mohamed.json', (err, result) => { if (!err) { console.log(result); } });
内容的提问来源于stack exchange,提问作者Habiba Mostafa Mahmoud
相关产品推荐
相关产品推荐

