为何我的异步函数中await未正常生效?递归未完成就提前返回结果
代码提前返回的根因
两个核心错误叠加,导致await链路完全失效:
- 首先是大家最容易踩的
forEach异步陷阱:forEach是完全同步的遍历方法,它根本不会感知传入的回调是不是async函数,触发完一轮回调就立刻往下走,完全不会等回调里的await执行完成。你在forEach里写的递归调用,实际上是在“后台”跑的,外层逻辑根本没等它结束。另外你在回调里写的famillesReliees = await getFamilies(...)其实是多余操作——数组是引用类型,递归函数里对数组的push修改,会直接作用在原引用上,不需要反复重新赋值接收返回值。 - 其次是你的Promise链路断了:你当前代码里的
await strapi.query(...),只等待了「查询单条分类数据」这一个操作的完成。当查询拿到结果进了.then回调后,你启动的那些子递归查询是没有被外层await“捕获”的,所以.then回调执行完(此时里面的异步递归根本还在跑),整个getFamilies函数就直接走到return语句,把还没收集完全的数组返回给上层了。
可行的修正方案
把同步的forEach替换成可等待的遍历逻辑,保证所有递归的异步任务都跑完了再返回结果:
- 优先用最直白的
for...of循环(逻辑简单,顺序执行所有递归,不容易出数组引用问题),修正后代码如下:
const getFamilies = async function (familyId, famillesReliees = []) { // 直接await接查询结果,不要嵌套then,Promise链路更清晰 const res = await strapi.query('famille-de-materiel').findOne({ id: familyId }) // 没有子分类,直接收集当前ID if (!res.cats_enfant?.length) { famillesReliees.push(res.id) return famillesReliees } // 用for...of遍历,每一个递归调用都会被完整等待 for (const enfant of res.cats_enfant) { await getFamilies(enfant.id, famillesReliees) } return famillesReliees } async search() { const value = await getFamilies(2, []) return value }
- 如果子分类节点很多、查询之间没有先后依赖,可以用
Promise.all并行执行所有子递归,减少整体等待时间:
// 替换上面for...of部分的代码即可 await Promise.all( res.cats_enfant.map(enfant => getFamilies(enfant.id, famillesReliees)) )
注意:不要在async递归的场景里用forEach,这是异步编程里非常常见的踩坑点——forEach没有内置的等待异步任务的能力,你写在回调里的await永远不会被外层逻辑感知。
内容的提问来源于stack exchange,提问作者ermat77
相关产品推荐
相关产品推荐

