foreach不等你拿回来的结果

朋友,有时候你可能会发现,用async和await时,数组里的东西怎么看都不够多。就算你在forEach里让它们去拿数据,最后发现啥也没填进去。这问题其实在于forEach不会真的停下来等你拿回来的结果。你想啊,它们只管把任务排好队接着往下跑,等你要打印数组的时候,那些异步任务可能还没回到家呢。就像前面那幅图里的蓝色块一样,程序直接跳过了等待环节,等到结果回来的时候,代码早就跑完了。 其实这事儿很简单,forEach跟async/await放一块儿就容易出错。比如你把一堆ID给到了一个数组里,想让每个ID去拿一个用户名存起来。代码写成这样:userIds.forEach(async (userId) => { ... }), 结果是啥?打印出来的usernames是空的。为啥?因为forEach的循环一启动就接着往下走了,print语句在结果回来之前就已经执行了。更可怕的是JS是单线程的,等所有数据真的回来时,整个函数都已经结束了。 所以咱们得换个思路:别让它们一股脑儿地去跑了。咱们可以用map把每个ID“变成”一个Promise对象(每个ID对应一次异步请求),然后把这些Promise对象“捆”在一起用Promise.all来打包。只有当所有小的Promise都解决了,这个大的Promise.all才会解开返回结果。 咱们来改一下之前的例子:const userIds = [1,2,3]; 把它们逐个变成Promise的对象集合,最后用await Promise.all来把这个集合“打开”。这样一来就保证了所有请求都回来了才会继续往下走。 比如这段代码: 把每个ID变成一次异步操作(返回Promise); 用Promise.all把这些小Promise“捆”成一根绳子; 只有绳子两端都系牢(所有请求都回来),绳子才会松开; 最后就得到了一个完整的用户名数组。 所以记住:如果在forEach里面看到了async/await就敲一下警钟。想等所有异步完成再继续?先把数组项映射成Promise,再用Promise.all收尾。别忘了:await只能单打独斗,面对多任务必须得靠“聚合器”Promise.all才能一次搞定。下次再遇到“异步结果为空”的代码时别急着抓头哦!