如何等待异步函数执行完成?TypeScript数据库种子场景答疑
问题解答
1. 修复seedDb,确保所有异步操作完成后再执行seedDb2
你的核心问题是seedDb里的map只是创建了一堆异步任务,但没有等待它们完成。修改方法很简单:用Promise.all包裹所有异步操作,并等待它完成。修改后的代码如下:
async function seedDb() { const users: Array<Users> = [ ... ]; // 用Promise.all等待所有upsert操作完成 await Promise.all(users.map(async (user) => { return prisma.user.upsert({ create: user, update: {}, where: { id: user.id } }); })); } async function main() { await seedDb(); // 现在这里会等待seedDb里所有upsert完成 await seedDb2(); // 此时用户数据已经写入数据库,可以安全执行 }
这样修改后,seedDb会等待所有prisma.user.upsert的Promise都resolve之后才会返回,main里的await seedDb()自然会等到所有数据库操作完成,再执行seedDb2。
2. TypeScript中类似threads.join()的实现方式
首先要明确:JavaScript/TypeScript是单线程异步模型,不存在像C++那样的“线程阻塞”——它不会暂停整个程序的执行,只会暂停当前async函数的执行流程,等待Promise完成,同时事件循环可以处理其他任务。
你要的“等待所有异步任务完成”的效果,就是通过Promise.all实现的:
users.map(...)会生成一个包含多个Promise的数组,每个Promise对应一个数据库操作Promise.all会返回一个新的Promise,只有当数组里所有Promise都成功resolve时,这个新Promise才会resolve- 用
await等待这个Promise.all的结果,就相当于C++里调用join()等待所有线程完成——只有所有异步任务都结束,当前async函数才会继续往下走。
3. await Promise.all()的意义
Promise.all()本身返回的是一个Promise对象,而不是直接返回解析后的结果数组。你需要用await来“解锁”这个Promise,拿到里面的实际结果。
举个例子:
const promises = [Promise.resolve(1), Promise.resolve(2)]; const result = Promise.all(promises); // result是Promise<number[]>,不是[1,2] const actualResult = await Promise.all(promises); // actualResult是[1,2]
至于return await Promise.all(...)和return Promise.all(...)的区别:
- 两者在功能上几乎等价,因为
async函数会自动把返回值包装成Promise - 唯一的差异是错误捕获:如果
Promise.all抛出错误,return await会让错误被当前函数的try/catch捕获;而直接return Promise.all的话,错误会被外层调用者的try/catch捕获。在你的场景里,两种写法都能保证main里的await seedDb()等待所有任务完成。
内容的提问来源于stack exchange,提问作者Heremit
相关产品推荐
相关产品推荐

