从Promise导出数组后,其他文件require时数据为空如何解决?
问题分析与解决方案
你的问题核心在于Node.js的模块加载机制是同步的,而你把module.exports放在了Promise的异步回调里执行——当fileB.js通过require加载fileA.js时,异步操作还没完成,回调里的赋值根本没执行,所以拿到的自然是空数据。
先看修复方案:导出Promise/异步函数,而非直接导出结果
Node.js里无法同步获取异步操作的结果,所以得把异步逻辑的控制权交给调用方(也就是fileB.js),有两种常用方式:
方式1:直接导出Promise
修改fileA.js:
const days = ["monday", "tuesday", "wednesday"] function dbRequest(day){ return knexInstance.select('shift_time',`${day}`).from('shr'); } // 直接导出Promise实例,让调用方自己处理异步 module.exports = Promise.all([ dbRequest(days[0]), dbRequest(days[1]), dbRequest(days[2]) ]);
然后在fileB.js里通过await或者then获取结果:
// 用async/await的方式(推荐) async function loadShiftData() { const shiftR = await require('./fileA'); console.log(shiftR); // 现在就能拿到正确数据了 } loadShiftData(); // 或者用then链式调用 require('./fileA').then(shiftR => { console.log(shiftR); });
方式2:导出异步函数
把数据获取逻辑封装成一个异步函数,调用方主动调用它:fileA.js:
const days = ["monday", "tuesday", "wednesday"] function dbRequest(day){ return knexInstance.select('shift_time',`${day}`).from('shr'); } async function getShiftData() { const results = await Promise.all([ dbRequest(days[0]), dbRequest(days[1]), dbRequest(days[2]) ]); return results; } module.exports = { getShiftData };
fileB.js:
const { getShiftData } = require('./fileA'); async function main() { const shiftR = await getShiftData(); console.log(shiftR); } main();
更优实现:减少数据库请求次数
你现在的写法会发起3次数据库查询,但其实可以一次查询就拿到所有需要的列,然后再把数据格式转换成你需要的数组结构,这样性能更好:
fileA.js优化版:
const days = ["monday", "tuesday", "wednesday"] async function getShiftData() { // 一次查询获取所有需要的列,避免多次请求数据库 const rawData = await knexInstance.select('shift_time', ...days).from('shr'); // 把原始数据转换成和之前Promise.all结果一致的格式 const shiftR = days.map(day => { return rawData.map(row => ({ shift_time: row.shift_time, [day]: row[day] })); }); return shiftR; } module.exports = { getShiftData };
这样既保证了数据格式和你原来的需求一致,又减少了数据库交互次数,效率更高。
内容的提问来源于stack exchange,提问作者ezg
相关产品推荐
相关产品推荐

