vue中遇到的函数执行顺序问题

发布时间 2023-11-18 22:44:41作者: 末雨摸鱼

vue中遇到的函数执行顺序问题

总结:vue中方法和方法间并未严格按照执行顺序执行的,可以使用asyncawait修饰符,使方法调用和执行是异步的。

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()
  }
}


函数AB 都发送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中,方法Aaxios请求方法不严格地按照顺序执行。

为避免出现这种情况,可以使用asyncawait修饰符,使方法调用和执行是异步的。

代码如下:

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函数里面