如何实现函数在if/else间循环执行并保证异步代码有序?
问题描述
需要实现一个按顺序执行的异步函数,核心逻辑如下:
- 遍历
result.data中的每个d:- 若
d.connector == null,执行axios_Func,请求出错则重试(偶发错误,重试即可成功) - 否则,判断
d.name是否在dev对象中:- 存在则直接执行
axios_DevFunc - 不存在则先执行
axios_ProdFunc,完成后再执行axios_DevFunc
- 存在则直接执行
- 若
现有代码执行完全无序,所有操作混乱触发,需修正以保证执行顺序。原代码如下:
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 createFunc = mainFunc((result, table_id) => { (async () => { let dev = await getTabs({ query: tables(123) }); let prod = await getTabs({ query: tables(321) }); result.data.forEach((d) => { if (d.connector == null) { axios_Func({ graphQL query }).then((response) => { if (response.data.errors) { // rerun function on errors } else console.log(JSON.stringify(response.data, null, 4)); }); } else { if (d.name in dev) { axios_DevFunc({ graphQL query }).then((response) => { console.log(`created from dev`); console.log(JSON.stringify(response.data, null, 4)); }); } else { axios_ProdFunc({ graphQL query }).then((response) => { .then((res) => res) .then((x) => { //repeat Dev Function after axios_ProdFunc is finished axios_DevFunc({ graphQL query }).then((response) => { console.log(`created from dev`); console.log(JSON.stringify(response.data, null, 4)); }); }); } } }); })(); });
解决方案
问题根源
forEach是同步遍历,不会等待内部异步操作完成,导致所有请求同时触发- 大量使用
.then()嵌套,逻辑混乱且无法保证串行执行 - 缺少重试逻辑的具体实现
- 存在语法错误(
axios_ProdFunc后多余的.then((res) => res))
修正方案
// 封装带重试逻辑的请求函数,可自定义重试次数 const axiosFuncWithRetry = async (config, maxRetries = 3) => { let retries = 0; while (retries < maxRetries) { try { const response = await axios_Func(config); if (response.data.errors) { throw new Error('GraphQL请求返回错误'); } return response; } catch (e) { retries++; console.log(`请求失败,重试第${retries}次...`, e); if (retries >= maxRetries) throw new Error('重试次数耗尽,请求最终失败'); // 重试前添加1秒延迟,避免频繁请求 await new Promise(resolve => setTimeout(resolve, 1000)); } } }; const mainFunc = (fn) => { return async (query_name, ...args) => { const result = await axios_Func(query_name); try { // 等待内部异步逻辑全部完成 await fn(result, ...args); } catch (e) { console.log('mainFunc执行出错:', e); } }; }; const createFunc = mainFunc(async (result, table_id) => { // 先获取dev和prod数据,确保这两个请求完成后再处理后续逻辑 const dev = await getTabs({ query: tables(123) }); const prod = await getTabs({ query: tables(321) }); // 用for...of遍历,保证每个元素的异步操作完成后再处理下一个 for (const d of result.data) { if (d.connector == null) { try { const response = await axiosFuncWithRetry({ /* 填入你的GraphQL query */ }); console.log(JSON.stringify(response.data, null, 4)); } catch (e) { console.log('请求最终失败:', e); } } else { if (d.name in dev) { const response = await axios_DevFunc({ /* 填入你的GraphQL query */ }); console.log(`created from dev`); console.log(JSON.stringify(response.data, null, 4)); } else { // 先执行prod请求,完成后再执行dev请求 await axios_ProdFunc({ /* 填入你的GraphQL query */ }); const devResponse = await axios_DevFunc({ /* 填入你的GraphQL query */ }); console.log(`created from dev`); console.log(JSON.stringify(devResponse.data, null, 4)); } } } });
关键改进点
- 串行遍历:用
for...of替代forEach,确保每个元素的异步操作完成后再处理下一个 - 重试逻辑:封装
axiosFuncWithRetry,自动处理偶发错误的重试 - 异步逻辑扁平化:用
await替代所有.then()嵌套,逻辑更清晰,执行顺序更可控 - 等待内部完成:
mainFunc中添加await fn(...),确保内部所有异步操作执行完毕
内容的提问来源于stack exchange,提问作者nb_nb_nb
相关产品推荐
相关产品推荐

