如何让TypeScript/JS异步函数完成后再执行后续任务?
问题解决:AWS Lambda中异步合并S3文件内容的正确姿势
修复后的核心代码
export async function handleFilesRequest(foundry: string, type: string): Promise<APIGatewayProxyResult> { try { // 1. 获取目标文件列表 const fileKeys = await getFileList(foundry, type); // 2. 并行处理所有文件:读取并转换内容 const allMaps = await Promise.all( fileKeys.map(async (key) => { const content = await readFile(key); return transformFile(content); }) ); // 3. 合并所有Map为一个 const accumulatingMap = new Map<string, any>(); allMaps.forEach(map => { map.forEach((value, key) => { accumulatingMap.set(key, value); }); }); // 4. 注意:Map无法直接JSON序列化,需转换为数组/普通对象 return OK.format(JSON.stringify(Array.from(accumulatingMap.entries()))); } catch (e) { return ServerError.format(e); } }
原代码问题分析
异步等待逻辑错误:
你混用了await和.then(),await getFileList(...).then(...)仅会等待getFileList完成以及then回调执行完毕,但then回调返回的是list.map(async key => ...)——这是一个Promise数组,而非已完成的处理结果。此时await得到的是这个数组,你用as Map<string, any>的类型断言只是骗过了TypeScript,实际运行时变量类型完全错误。
同时,你在.then()回调里修改外部的accumulatingMap,这些修改是异步执行的,函数主线程已经走到return语句,导致返回时合并操作还未完成。隐藏的序列化问题:
原代码中JSON.stringify(accumulatingMap)会直接输出{},因为Map对象默认不支持JSON序列化,必须先转换为数组或普通对象。
await的实际作用
await的核心是暂停当前async函数的执行流程,直到右侧的Promise状态变为「已兑现」,然后返回Promise的兑现值;如果右侧不是Promise,则直接返回该值。
它的使用有两个关键前提:
- 必须在标记为
async的函数内部使用; - 它仅等待单个Promise的兑现,如果要等待多个异步操作完成,必须配合
Promise.all()(并行)或Promise.allSettled()等方法——因为Promise.all()会返回一个新Promise,只有当所有传入的Promise都兑现时才会兑现,此时await Promise.all(...)才能确保所有异步操作完成后再继续执行后续代码。
原代码的误区在于,你误以为await会等待map里的所有异步操作,但实际上它只等待到了getFileList().then()返回的Promise数组,并没有等待数组内的每个Promise完成。
内容的提问来源于stack exchange,提问作者Michael Coxon
相关产品推荐
相关产品推荐

