为何使用await后row.already_messaged_clients无法被赋值?
问题
以下代码能正常设置row.already_messaged_clients,且该属性在循环外部可访问:
businesses.forEach(async function(row) { // let already_messaged_clients_arr = await getAlreadyMessagedClientsForPlaceID(row.place_id); row.already_messaged_clients = 3; });
但加入await调用后,row.already_messaged_clients却无法被设置:
businesses.forEach(async function(row) { let already_messaged_clients_arr = await getAlreadyMessagedClientsForPlaceID(row.place_id); row.already_messaged_clients = 3; });
请问这是什么原因?
原因分析
- forEach不等待异步函数执行:
forEach的运行逻辑是快速遍历所有元素,把每个异步回调函数扔进事件队列就继续下一个循环,完全不会等待回调里的异步操作(比如await的请求)完成。你在循环外部访问row时,那些带await的回调可能还没执行到赋值语句,自然就看不到设置后的属性。 - 无await时是同步执行:第一种代码里虽然用了
async函数,但没有await阻塞,赋值操作是同步完成的,forEach遍历过程中会立刻执行赋值,所以循环外部能拿到更新后的值。 - 可行的解决方式:如果需要等所有异步操作完成后再处理后续逻辑,别用
forEach,换这两种方式:// 方式一:for...of循环配合await for (const row of businesses) { let already_messaged_clients_arr = await getAlreadyMessagedClientsForPlaceID(row.place_id); row.already_messaged_clients = 3; } // 方式二:用Promise.all批量等待异步任务 await Promise.all(businesses.map(async row => { let already_messaged_clients_arr = await getAlreadyMessagedClientsForPlaceID(row.place_id); row.already_messaged_clients = 3; }));
内容的提问来源于stack exchange,提问作者TMO
相关产品推荐
相关产品推荐

