如何让后续代码等待含异步操作的循环执行完成?
解决方案
你的问题核心是异步操作不会阻塞同步代码,rest.get返回的是Promise,它的.then()回调会在后续事件循环中执行,而循环和console.log(b)是同步代码,所以后者会先跑完,此时异步回调还没处理完b的更新。另外你的代码还有个问题:每次循环都调用rest.get,会重复请求API,还会覆盖之前的b值,导致之前的添加操作失效。
下面是两种修复方案:
方案一:先获取一次现有命令,批量处理模块(推荐)
把API请求提到循环外,只执行一次,然后遍历模块检查并更新命令数组:
async function updateCommands() { // 一次性获取所有现有应用命令 const existingCommands = await rest.get(Routes.applicationCommands("BLAH")); // 复制一份数组,避免直接修改原请求结果 const updatedCommands = [...existingCommands]; // 遍历所有模块 for (const moduleName of res) { const foo = require(`./modules/${moduleName}`); // 检查当前命令是否已存在 const commandExists = updatedCommands.some(cmd => cmd.name === foo.name); if (!commandExists) { updatedCommands.push({ name: foo.name, description: foo.description, }); } } // 此时所有模块处理完成,输出结果 console.log(updatedCommands); // 如果需要提交更新到API,可以在这里调用 rest.put(Routes.applicationCommands("BLAH"), { body: updatedCommands }) } // 执行异步函数,同时捕获可能的错误 updateCommands().catch(err => console.error('处理命令时出错:', err));
方案二:用Promise.all处理循环中的异步操作(适用于每个模块需要单独异步请求的场景)
如果必须在循环中发起异步请求,收集所有Promise并等待全部完成:
async function processModules() { // 先获取初始命令列表 const initialCommands = await rest.get(Routes.applicationCommands("BLAH")); const updatedCommands = [...initialCommands]; // 收集所有异步处理的Promise const processingPromises = res.map(async (moduleName) => { const foo = require(`./modules/${moduleName}`); // 这里如果需要每次获取最新命令,可以保留请求,否则建议用方案一的一次性请求 const currentCommands = await rest.get(Routes.applicationCommands("BLAH")); const commandExists = currentCommands.some(cmd => cmd.name === foo.name); if (!commandExists) { return { name: foo.name, description: foo.description }; } return null; }); // 等待所有异步操作完成 const newCommands = await Promise.all(processingPromises); // 过滤掉null值,合并到命令数组 updatedCommands.push(...newCommands.filter(cmd => cmd !== null)); console.log(updatedCommands); } processModules().catch(err => console.error('处理命令时出错:', err));
关键说明
async/await是Promise的语法糖,能让异步代码看起来像同步代码,避免回调嵌套。Promise.all会等待所有传入的Promise都完成后,返回一个包含所有结果的数组,适合批量处理异步任务。- 避免在循环中重复发起相同API请求,不仅浪费资源,还会导致数据覆盖的问题。
内容的提问来源于stack exchange,提问作者DTD-123
相关产品推荐
相关产品推荐

