问题的背景
最近在做自己的项目的时候,遇到了一个问题.我在组件里面监听了一个对象的变化.一旦发生变化.先通过这个对象的 ID 去进行异步请求.获取到一个属性:URL(播放地址).然后将这个属性绑定到 audio 的 src 属性上.然后再去利用 this.$refs 获取 dom 调用 radio.play 方法.
代码
currentSong() {
var v = this;
v.loadSongUrl(id);
v.$nextTick(() => {
v.$refs.audio.play();
});
},
遇见的问题
vue 异步请求成功之后,还没绑定数据就立即去执行获取 dom 元素了.
示意流程
正确: currentSong 变化 -> 进行异步请求 -> 绑定数据到 dom -> 获取 dom 错误:(遇到的情况) currentSong 变化 -> 进行异步请求 -> 获取 dom ->绑定数据到 dom
问题分析
为什么会有这样的情况出现?其实这里是连续的异步调用.在第一次进行异步请求 URL 之后.在同步队列中.我的异步请求完成之后会加入到‘任务队列’中.所以会马上去执行同步队列的任务.
解决方法
v.loadSongUrl(id).then(() => {
v.$nextTick(() => {
v.$refs.audio.play()
})
})
同时必须给 loadSongUrl 添加 return:
return v.$axios
.get("api/song/url", {
params: {
id: songsIds
}
})
.then((response) => {
//console.log(response.data.data);
if (response.data.code === 200) {
songUrlList = response.data.data
//console.log(songUrlList);
v.manageSongList(list, songUrlList)
}
})
.catch((error) => {
console.log(error)
})
原理
在 ES6 中.有封装 promise.then()方法.这个方法保证多个异步请求按序进行.回调函数中会把上一个 then 中返回的值当做参数值供当前 then 方法调用.then 方法执行完毕后需要返回一个新的值给下一个 then 调用(没有返回值默认使用 undefined).也就是说.每个 then 只可能使用前一个 then 的返回值.有了这个方法.就能保证去获取 dom 之前.先去绑定 dom 的效果.