Node.js中async异步函数返回数组为空或值为undefined问题求解
问题原因说明
第一种写法返回空数组的原因
- JS内置的
Array.prototype.forEach是同步迭代方法,本身不会返回Promise,你在它前面加await没有任何作用,执行完forEach会直接走到后续的打印和返回逻辑,此时内部所有User.findById的异步查询还没有执行完成,.then回调还没触发,所以emailList还是空数组。
第二种写法元素全为undefined的原因
User.findById是Mongoose提供的异步查询方法,调用后返回的是Pending状态的Promise实例,而非直接返回查询结果。你没有加await就直接读取workerEmail属性,Promise实例上不存在该属性,自然只能拿到undefined,存入数组的全是undefined。
和Python控制流的差异说明
Python的异步迭代有async for等原生语法支持,内部会自动等待异步任务完成,但JS的常规数组迭代方法(forEach/for in等)都没有内置异步支持,不会等待你传入的异步回调执行完成,有Python开发背景很容易踩这个坑。
正确实现方式
推荐使用Promise.all搭配map来实现批量异步查询的等待,所有异步查询完成后会自动组装成结果数组:
exports.getUserEmailByAccess = async (moduleType) => { const foundUsers = await Access.find({moduleType: moduleType}) console.log(foundUsers); const emailList = await Promise.all( foundUsers.map(async access => { const foundUser = await User.findById(access.userId) console.log(foundUser.workerEmail) return foundUser.workerEmail }) ) console.log(emailList) return emailList }
如果需要按顺序串行查询而非并行,也可以用常规的for of循环,它支持内部的await等待:
exports.getUserEmailByAccess = async (moduleType) => { let emailList = [] const foundUsers = await Access.find({moduleType: moduleType}) console.log(foundUsers); for (const access of foundUsers) { const foundUser = await User.findById(access.userId) console.log(foundUser.workerEmail) emailList.push(foundUser.workerEmail) } console.log(emailList) return emailList }
内容的提问来源于stack exchange,提问作者Saurabh
相关产品推荐
相关产品推荐

