Node.js 如何在异步递归函数全部执行完成后运行后续逻辑
核心问题原因
你现在的代码存在两个导致无法等待递归全部完成的问题:
- 调用
__recoveryRecursive时没有加await,主控制器不会等待递归执行完成,就会直接走后续逻辑返回响应 - 递归内部的
update类异步方法、递归调用自身的逻辑都没有加await,导致异步操作状态无法被追踪,会游离在主流程之外
修复方案
给所有异步操作补充await关键字即可,修改后的完整代码如下:
const recoveryCategory = async (req, res) => { try { const categoryId = req.params.categoryId const category = await nmCategorySvcV2.getByIdDeleted(categoryId) if (category === null){ throw new Error("This category is not deleted.") } // 加await等待递归完全执行完毕 await __recoveryRecursive(categoryId) // 此处即可放置递归结束后需要执行的逻辑 res.json({ success: true, message: "Success." }) } catch (err){ res.json({ success: false, message: err.message }) } } const __recoveryRecursive = async (categoryId) => { const category = await nmCategorySvcV2.getByIdDeleted(categoryId) if (category === null){ return } await nmCategorySvcV2.update(categoryId, { deleted: false }) const categoryItens = await categoryItemSvcV2.getAllItensByCategory(categoryId) for (let i = 0; i < categoryItens.length; i++) { const categoryItem = categoryItens[i] if (categoryItem.deleted == true) { const item = await itemSvcV2.getByIdNoPopulate(categoryItem.item, categoryItem.page) if (item.deleted == true) { // 补充await追踪异步操作完成状态 await itemSvcV2.update(item._id, { deleted: false }) await categoryItemSvcV2.updateItensProp(item._id, { deleted: false }) } const itemPrice = await itemPriceSvcV2.getById(categoryItem.price) if (itemPrice.deleted == true) { // 补充await追踪异步操作完成状态 await itemPriceSvcV2.updateObject({ _id: itemPrice._id }, { deleted: false }) } // 补充await追踪异步操作完成状态 await categoryItemSvcV2.update(categoryItem._id, { deleted: false }) if (categoryItem.next_steps.length > 0){ for (let j = 0; j < categoryItem.next_steps.length; j++){ const categryNextStep = categoryItem.next_steps[j].category // 递归调用补充await,等待子分类递归逻辑全部完成 await __recoveryRecursive(categryNextStep) } } } } }
可选优化
如果业务允许子分类并行恢复,不需要按顺序执行,可以把next_steps的循环部分改成Promise.all提升执行效率:
if (categoryItem.next_steps.length > 0){ const recoveryPromises = categoryItem.next_steps.map(item => __recoveryRecursive(item.category)) await Promise.all(recoveryPromises) }
内容的提问来源于stack exchange,提问作者Thyi
相关产品推荐
相关产品推荐

