Promise.all 链式函数调用执行顺序问题
handleGroups() {
Promise.all(
this.groups.map(g => {
g.videoDtos = []
g.videos.split(',').map(async (id) => {
let v = await this.getVideoById(Number(id));
if (v) g.videoDtos.push(v)
})
})
).then(res => {
this.playGroups()
})
}
这里理想的执行顺序是当 g.videoDtos得到所有的结果,再去执行playGroups(),但是事实是当执行到g.videos.split(',').map(async (id)这一步,就直接跳到了playGroups(),然后再去执行getVideoById(Number(id))
getVideoById(id: number) {
return new Promise((resolve, reject) => {
getVideoDto(id).then(res => {
if (res.data.code == 200) {
let video: Video = res.data.data
resolve(video)
} else {
reject();
}
})
})
}
playGroups() {
let videos = this.groups[this.playGroupsIndex].videoDtos;
// 放一堆视频
if (videos.length > 0)
this.$refs.videoBoxRef.setVideos(videos);
this.playGroupsTimer = setTimeout(()=>{
this.playGroupsIndex = (this.playGroupsIndex + 1) % this.groups.length;
this.playGroups();
}, this.roundTime * 1000);
}
想问下,如何才能让这个链式调用起作用,等getVideoById(Number(id))都执行完之后,再去执行.then中的playGroups()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
先看注释
然后一步步分析
首先,既然内部用到了
await
,那外面也没必要客气,用await
可以逻辑更容易懂,所以不过
res
拿到之后并没有使用,不需要,可以直接把const res =
丢掉。接下来
Promise.all()
的参数是一个数组,如果数组的元素是 Promise 对象,会等待它resolve()
;如果是普通对象或undefined
等,就不需要等待。Promise.all()
会返回一个Promise
对象,它会在参数数组中所有 Promise 对象都 resolved 之后resolve()
。不妨拆一下这个调用,变成
现在的问题是
groupPromises
是什么东西。它既然是从this.group.map(fn)
返回的,那一定是一个数组,而其中有元素,是fn
执行后的返回值。这里fn
是g => { ... }
,很显然,没有返回值,所以groupPromises
现在是由一堆undefined
组成的数组。显然这不是需要的结果,应该它
g => { ... }
加上返回值,而且这个返回值得是 Promise 对象才对得起Promise.all()
。那该返回什么?接下来看
g => { ... }
的内部逻辑。它的内部是要异步处理某个 group 中的若干 videos。同上面类似的分析,可以知道
g.videos.split(",").map(async () => {})
返回的是一个由若干 Promise 对象组成的数组。需要注意的是this.getVideoById(Number(id))
虽然返回 Promise 对象,但是已经有await
等过了;但是它外面包的async () => {}
会产生另一个 Promise 对象,也就是map
的返回值,并没有谁在等。当然可以用for
循环来等(注意不是.forEach()
)不过既然是并发处理,可以用Promise.all()
组织起来一起等,所以可以改为好了,注意,这里的
await
不是修饰的map()
回调,它的外层函数需要使用async
,所以g => { ... }
要变成async g => { ... }
。是不是顺手就把g => { ... }
的返回值变成 Promise 对象了(前面说过需要返回 Promise 对象的)?所有逻辑都分析过多了,把整个过过程连起来,就是正确的结果
Promise.all
是接受一个promise的列表,你map出来的并不是一个promise实例数组,在你的基础上给你改下首先指出你的问题,
这里这一块内容你出现了歧义,应该就是你出现问题的部分。就算如你意愿,最后
this.groups.map
的返回值会是这样的[[promise0-0,pormise0-1,promise0-2],[promise1-0,pormise1-1,promise1-2],...]
所以应该要把外部包裹的数组给推平,大概实现demo:
因为在你的第一层
this.groups.map
中回调函数全部默认返回了undefined
,传入Promise.all
中的是一个undefined
数组,Promise.all
会对其中的每一个值使用Promise.resolve()
进行处理,全部返回fullfilled
状态的Promise,Promise.all onFullfilled
成立。 因此直接执行then
语句了。推测你的
this.groups
数据结构如下:将你代码拆了下,逻辑变清晰了,你可以试试:
希望能解答你的问题~