如何在两个互相调用的异步函数执行完后合并结果并调用第三个函数
问题与解决方案
问题描述
我有两个互相调用的函数createOne和createTwo,二者会持续调用直到forEach循环执行完毕。我希望在这两个函数完全执行完所有代码后调用第三个函数createThree,同时将执行过程中输出的非空数组合并成一个完整数组,遍历这个数组调用createThree。
原代码
const mainFunc = (fn) => { return async (query_name, ...args) => { const result = await axios_Func(query_name); try { return fn(result, ...args); } catch (e) { console.log(e); } }; }; const createOne = mainFunc((result) => { let table_id = result.data.internal_id; axios_Func({ graphQL query }).then((response) => { createTwo({ query: graphQL_query, table_id).then((res) => res); }); }); createTwo = mainFunc(async (result, table_id) => { let dev = await getAllTables({ query: tables(123) }); let prod = await getAllTables({ query: tables(321) }); let prod_id = new Set(); result.data.data.table.table_fields.forEach((d) => { if (d. connector != null && !(d.name in dev)) prod_id.add(prod[d.name]["id"]); }); prod_id = [...prod_id]; console.log(prod_id); await Promise.all( prod_id.map((x) => createOne({ query: graphQL_query(x) }).then((res) => res)) ); }); const createThree = mainFunc(async (result, table_id) => { //do something });
当前输出
[123, 456] [] [567, 897] [345, 987] []
解决方案
核心问题是当前代码未正确处理异步函数的返回值,导致无法追踪所有createOne和createTwo的执行完成状态,也没法收集非空的prod_id数组。通过以下修改可实现需求:
- 让
createOne返回完整的Promise链,确保异步操作被正确追踪 - 新增数组用于收集所有非空的
prod_id - 在所有异步操作完成后,遍历收集到的数组调用
createThree
修改后的代码
// 收集所有非空的prod_id元素 const collectedProdIds = []; const mainFunc = (fn) => { return async (query_name, ...args) => { const result = await axios_Func(query_name); try { return fn(result, ...args); } catch (e) { console.log(e); } }; }; // 修改createOne,返回完整Promise链,确保上层能捕获异步操作 const createOne = mainFunc((result) => { let table_id = result.data.internal_id; return axios_Func({ graphQL query }).then((response) => { return createTwo({ query: graphQL_query, table_id }); }); }); // 修改createTwo,收集非空数组并返回Promise链 createTwo = mainFunc(async (result, table_id) => { let dev = await getAllTables({ query: tables(123) }); let prod = await getAllTables({ query: tables(321) }); let prod_id = new Set(); result.data.data.table.table_fields.forEach((d) => { if (d.connector != null && !(d.name in dev)) prod_id.add(prod[d.name]["id"]); }); prod_id = [...prod_id]; console.log(prod_id); // 仅收集非空数组 if (prod_id.length > 0) { collectedProdIds.push(...prod_id); } // 返回Promise.all结果,确保所有createOne调用完成后才标记当前createTwo执行完毕 return Promise.all( prod_id.map((x) => createOne({ query: graphQL_query(x) })) ); }); const createThree = mainFunc(async (result, table_id) => { //do something }); // 入口函数,启动流程并等待所有操作完成后调用createThree async function run() { // 传入初始调用参数,等待所有递归的createOne/createTwo执行完毕 await createOne(/* 你的初始query_name参数 */); // 遍历收集到的数组调用createThree for (const id of collectedProdIds) { await createThree(/* 对应query_name和id参数 */); } } // 执行入口 run();
关键说明
- Promise链返回:
createOne必须返回内部异步操作的Promise,否则上层await无法捕获后续异步流程,会提前判定执行完成。 - 非空数组收集:通过
collectedProdIds直接合并非空数组的元素,避免空数组混入最终结果。 - 入口函数控制:用
run函数包裹初始调用,确保所有递归的异步操作全部完成后,再统一执行createThree。
内容的提问来源于stack exchange,提问作者nb_nb_nb
相关产品推荐
相关产品推荐

