如何等待含异步操作的For循环执行完毕后再运行后续代码?
问题原因
ddb.get是异步操作,它的回调函数会在后续事件循环中执行,而你的console.log(token)是同步代码,会在所有异步请求还没返回结果时就执行,所以此时token还是空数组。
解决方法
需要把异步操作转为Promise形式,然后等待所有异步操作完成后再打印结果,以下是两种常用实现方式:
方式一:用Promise.all批量等待异步操作
先把ddb.get包装成返回Promise的函数,再遍历生成所有Promise实例,最后用Promise.all等待全部请求完成:
// 把ddb.get包装为Promise版本 const getDdbItem = (username) => { return new Promise((resolve, reject) => { ddb.get({ TableName: "DB", Key: { Username: username } }, (err, data) => { if (err || Object.keys(data).length === 0) { console.log(err); resolve(undefined); // 失败时返回undefined,不中断后续请求 } else { resolve(data.Item.token); } }); }); }; // 处理逻辑 async function getTokens() { const tokenPromises = []; // 注意:数组索引从0开始,原代码i从1开始会漏掉第一个元素 for (let i = 0; i < offlineMembers.length; i++) { const member = offlineMembers[i]; if (typeof member === 'string') { tokenPromises.push(getDdbItem(member)); } } // 等待所有异步请求完成,收集结果 const tokenList = await Promise.all(tokenPromises); // 过滤掉请求失败返回的undefined const validTokens = tokenList.filter(item => item !== undefined); console.log(validTokens); } // 调用执行 getTokens();
方式二:用for...of逐个等待异步操作
这种方式会按顺序执行每个异步请求,适合需要严格顺序处理的场景:
const getDdbItem = (username) => { return new Promise((resolve, reject) => { ddb.get({ TableName: "DB", Key: { Username: username } }, (err, data) => { if (err || Object.keys(data).length === 0) { console.log(err); resolve(undefined); } else { resolve(data.Item.token); } }); }); }; async function getTokens() { const token = []; for (const member of offlineMembers) { if (typeof member === 'string') { const tokenItem = await getDdbItem(member); if (tokenItem) { token.push(tokenItem); } } } console.log(token); } getTokens();
额外注意点
原代码的循环条件i <= offlineMembers.length存在索引错误:数组索引从0开始,最后一个元素的索引是offlineMembers.length - 1,原写法会访问到offlineMembers[offlineMembers.length](值为undefined),建议改成i < offlineMembers.length或者用for...of直接遍历元素,避免这类问题。
内容的提问来源于stack exchange,提问作者user15376850
相关产品推荐
相关产品推荐

