vue
中遇到的函数执行顺序问题
总结:vue
中方法和方法间并未严格按照执行顺序执行的,可以使用async
和await
修饰符,使方法调用和执行是异步的。
在vue
中的方法调用顺序是依次进行的,方法体内部也是依次执行的, 但是,两个方法体的执行顺序并不能严格控制,也就是说,并不一定是先执行完第一个方法后再执行后一个。
可以这样理解:任务表上有两个任务,它们按顺序排列,方法调用顺序是依次进行的
就是将这两个任务按照顺序依次发布给工作者,但因为工作者不止一个,所以第一个任务发布给第一个人,第二个任务给第二个人;又因为任务的复杂性不一致,所以每个人完成对应任务的时间不同,可能会出现第二个任务先完成、第一个任务后完成的情况,即执行顺序并不能严格控制
。
举个例子:函数B
中需要使用一个变量T,这个变量T一开始是没有值的,执行函数A
后变量T才有值,所以要先执行函数A
,再执行函数B
,一般情况下,CPU速度足够快,这并不会有问题。但在发送axios
请求时,由于网络的不稳定,或者服务器的带宽不够等情况,会导致函数A
所需的时间开销大于函数B
,函数B
已经执行完,并结束了,函数A
还没完成,这显然会造成错误。
例如:
export default {
name: 'xxx',
data() {
return {
a: [],
b: [],
T: '',
}
},
methods: {
A() {
this.$axios.get(this.$httpUrl + '/a/list').then(res => res.data).then(
res => {
console.log('A')
if (res.code === 20041) {
for(let i = 0; i < 10000; i++) {
this.a = res.data
}
T = res.data.length
}
)
},
B() {
this.$axios.get(this.$httpUrl + '/b/list').then(res => res.data).then(
res => {
console.log('B')
if (res.code === 20041) {
this.b = T + res.data
}
}
)
}
},
mounted() {
this.A()
this.B()
}
}
函数A
、B
都发送axios
请求,但函数A
内存在一个无意义的循环代码(举例,夸张举例,正常情况不会出现这么愚蠢的代码),执行函数A
所需要的开销大于函数B
,虽然在mounted()
中的顺序是先执行A
,再执行B
,但通过控制台可以发现,B
先输出,A
后输出。进一步推断:如果函数B
中需要用到 通过函数A
得到的值 时,显然会产生错误。
哪怕将函数A
放在函数B
中(代码如下),也并不会有作用。
export default {
name: 'xxx',
data() {
return {
a: [],
b: [],
T: '',
}
},
methods: {
A() {
this.$axios.get(this.$httpUrl + '/a/list').then(res => res.data).then(
res => {
console.log('A')
if (res.code === 20041) {
for(let i = 0; i < 10000; i++) {
this.a = res.data
T = res.data.length
}
}
)
},
B() {
this.A()
this.$axios.get(this.$httpUrl + '/b/list').then(res => res.data).then(
res => {
console.log('B')
if (res.code === 20041) {
this.b = T + res.data
}
}
)
}
},
mounted() {
this.B()
}
}
只不过之前是函数A
和函数B
不严格地按照顺序执行,而现在是在函数B
中,方法A
和axios
请求方法不严格地按照顺序执行。
为避免出现这种情况,可以使用async
和await
修饰符,使方法调用和执行是异步的。
代码如下:
export default {
name: 'xxx',
data() {
return {
a: [],
b: [],
T: '',
}
},
methods: {
A() {
this.$axios.get(this.$httpUrl + '/a/list').then(res => res.data).then(
res => {
console.log('A')
if (res.code === 20041) {
for(let i = 0; i < 10000; i++) {
this.a = res.data
T = res.data.length
}
}
)
},
async B() {
await this.A()
this.$axios.get(this.$httpUrl + '/b/list').then(res => res.data).then(
res => {
console.log('B')
if (res.code === 20041) {
this.b = T + res.data
}
}
)
}
},
mounted() {
this.B()
}
}
async
表明该函数是异步函数。
await
表示等待 —— await
后面的函数运行完并且有了返回结果之后,才继续执行下面的代码。
注意: await
关键字只能放到async
函数里面