NodeJS中如何在不同异步回调函数内更新外部定义的数组?
问题原因
当前返回空数组的核心原因是fetchAll属于异步回调方法,JS主线程执行时不会等待回调逻辑执行完成,会直接运行末尾的res.send语句,此时两个异步查询的回调都还没触发,ans数组还没被赋值,所以返回的是空数组。
解决方案1:Promise + Promise.all 实现(最推荐)
先将回调风格的fetchAll包装为Promise,再用Promise.all并行执行两个查询,全部完成后再返回响应:
// 封装回调转Promise的通用工具 function promisifyFetch(model, date) { return new Promise((resolve, reject) => { model.fetchAll(date, (err, data) => { if (err) return reject(err) resolve(data) }) }) } // 接口处理逻辑 async function yourApiHandler(req, res) { try { // 并行执行两个查询,等待全部返回结果 const [countryData, stateData] = await Promise.all([ promisifyFetch(Country, newdate), promisifyFetch(State, newdate2) ]) const ans = [countryData, stateData] res.send({ status: 201, data: ans }) } catch (err) { res.status(500).send({ message: err.message || "Some error occurred while retrieving data." }) } }
该方案优势是两个查询可以并行执行,性能更好,代码逻辑清晰易维护。
解决方案2:回调计数器实现(无需修改原有回调写法)
如果不想改动原有回调风格的代码,可以用计数器统计已完成的异步任务数量,等两个任务全部完成后再返回响应:
var ans = [] // 总异步任务数 const totalTask = 2 // 已完成任务计数器 let finishedCount = 0 // 任务完成校验逻辑 function checkIfAllDone() { if (finishedCount === totalTask) { res.send({ status: 201, data: ans }) } } Country.fetchAll(newdate,(err, data) => { if (err) { return res.status(500).send({ message: err.message || "Some error occurred while retrieving data." }); } ans.push(data); finishedCount++ checkIfAllDone() }); State.fetchAll(newdate2,(err, data) => { if (err) { return res.status(500).send({ message: err.message || "Some error occurred while retrieving data." }); } ans.push(data); finishedCount++ checkIfAllDone() });
使用该方案需要注意所有逻辑分支都要正确更新计数器,避免出现接口无响应的问题。
内容的提问来源于stack exchange,提问作者Mukund Chourey
相关产品推荐
相关产品推荐

