You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在for循环中等待异步函数执行完成?

解决异步调用等待所有完成的问题

我来帮你搞定这个等待所有异步数据库调用完成的问题~先梳理下你现有代码的核心问题,再一步步给出修复方案:

现有代码的核心问题

  1. Promise.all使用错误:你传给Promise.all的是Vacation对象数组,但它需要接收Promise实例数组才能追踪并等待所有异步任务完成。
  2. 异步任务未被追踪:循环里调用find_creator后,只是通过.then悄悄push对象,没有把每个异步操作的Promise收集起来,导致无法判断所有任务是否完成。
  3. this指向隐患:find_creator里的Promise回调用了普通函数,你用self = this虽然能绕开问题,但用箭头函数会更简洁安全。

修改后的完整代码

第一步:修复Vacation类的find_creator方法

class Vacation {
 constructor(id, destination, description, attendee_creator_id) {
  this.id = id;
  this.destination = destination;
  this.description = description;
  this.attendee_creator_id = attendee_creator_id;
  this.creator = undefined;
  this.votes = undefined;
 }
 find_creator(pool){
  // 用箭头函数,this自动绑定当前Vacation实例,无需额外存self
  return new Promise((resolve, reject) => {
   var query = "SELECT * FROM vacation_attendee WHERE id = " + this.attendee_creator_id;
   pool.query(query, (error, result) => {
    if (error) {
     console.log("Error in query for vacation creator " + error);
     return reject(error);
    }
    var creator = new attendee.VacationAttendee(result.rows[0].full_name, result.rows[0].email, result.rows[0].password_hash);
    this.creator = creator;
    console.log("creator found ----> " + this.creator.full_name + " in " + this.destination);
    resolve(this); // resolve时直接返回当前实例,方便后续收集
   });
  })
 }
}

第二步:修复loop_through_vacations函数

现在我们要主动收集每个异步任务的Promise,再用Promise.all等待全部完成:

async function loop_through_vacations(vacations_incomplete, pool) {
 // 用map遍历,把每个vacation数据转换成"加载完creator的Promise"
 const vacationPromises = vacations_incomplete.map(vacation_data => {
  const vacation = new vac.Vacation(vacation_data.id, vacation_data.destination, vacation_data.description, vacation_data.attendee_creator_id);
  // 返回find_creator的Promise,resolve后会得到填充好creator的实例
  return vacation.find_creator(pool);
 });

 // 等待所有异步任务完成,拿到最终的完整vacation数组
 const all_vacations = await Promise.all(vacationPromises);
 console.log("所有vacation的创建者信息已加载完成");
 return all_vacations;
}

第三步:修复get_all_vacations函数

因为loop_through_vacations是async函数,会返回Promise,所以要正确处理它的结果:

function get_all_vacations(callback) {
 var sql_vacations_query = "SELECT * FROM vacation";
 pool.query(sql_vacations_query, (error, vacations_query_result) => {
  if (error) {
   console.log("error in vacations query " + error);
   return callback(error);
  }
  // 调用async函数,用.then处理成功结果,.catch处理错误
  loop_through_vacations(vacations_query_result.rows, pool)
   .then(all_complete => {
    callback(null, all_complete);
   })
   .catch(err => {
    callback(err);
   });
 });
}

关键逻辑说明

  • Promise.all的作用:它会等待传入的所有Promise都成功resolve后,返回一个包含所有resolve结果的数组;如果有任何一个Promise失败,会立即抛出对应的错误。
  • 用map替代for循环:map可以更简洁地把原始数据转换成异步任务的Promise数组,避免手动维护数组的麻烦。
  • resolve返回实例:在find_creator里直接resolve当前Vacation实例,这样Promise.all完成后就能直接拿到所有已填充好数据的对象,无需额外处理。

这样修改后,就能确保所有异步数据库调用都完成后,才会执行后续的回调逻辑啦~

内容的提问来源于stack exchange,提问作者Gama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:54:31