前言

问题:最常见的就是一个异步函数调用成功,另一个函数需要用到这个接口的返回值或者处理值,由于异步机制问题,可能会导致下一个函数还没有拿到上一个函数的返回值就开始调用了,这个时候我们可以通过回调函数解决问题,由于回调函数私有变量过多会造成内存滥用且代码繁冗,而es6promise的出现让我们处理起来更加简洁,以更简洁的代码完成同样的功能也是个人随推崇的。


一、promise是什么?

Promise 是异步编程的一种解决方案,其实是一个构造函数, 简单来说也就是一个容器,里面装着一个未来才会完成的事件(就是异步操作)。通过Promise.then().catch()等链式语法可以实现异步代码的同步化,一旦执行就不能取消。
promise有三种状态

  • Pending(进行中)
  • Resolved(已完成,又称 Fulfilled)
  • Rejected(已失败)

Pending直接过渡到Resolved或者Rejected,一旦状态改变,就不会再变。
以上只是简单理解,具体详细可参照:promise的理解

二、使用场景

1.普通异步函数同步化处理

(1)一个函数需要另一个函数的返回值才能调用

日常调用异步函数

methods:{
    testOne(){
      setTimeout(function () { //第一个异步函数,模拟异步操作
        return '我是第一个函数的返回值'
      },500)
    },
    testTwo(data){ //第二个异步函数
      console.log(data)
      console.log('得到data进行下一步的操作')
    },
    resultFn(){
     let data=this.testOne() //取到第一个函数的返回值传递给第二个函数
         this.testTwo(data)
    },
}

通过调用resultFn函数即可得到如下结果
在这里插入图片描述
从上图可以看出,调用第二个函数并没有拿到第一个函数的返回值,所以打印为undefined,当然这里你可能会提出为什么不直接在第一个函数的返回值里面调用第二个函数呢,当然你这样调用其实也是没问题的,我这样调用可能遵循的一个模块化思想,每个函数都有自己的作用域,你可能其他地方单单只是调用了第一个函数或者调用了第二个函数,写在一起的话就不便于维护与调用了,加入promise的调用让我们的代码更加简洁与维护。

注意

  1. promise必须调用resolve才能执行then()里面的语法,且then函数里面的参数就是resolve传递的参数。同样要想执行catch()里面 的方法必须调用reject
  2. 调用内部含有promise的异步函数其返回值是一个promise实例(Promise {<pending>}),通过调用then(res =>{}),res就是promise实例解析的实际参数。

修改后参照代码如下:

methods:{
   testOne(){
      return new Promise((resolve,reject) =>{
        setTimeout(function () { //模拟异步操作,延时函数可以换成你需要的axios或者ajax请求
         resolve('我是第一个函数的返回值')
        },500)
      })
    },
    resultFn(){
      this.testOne().then(res =>{
        console.log(res)
        console.log('得到res执行下一步操作')
      })
    },
}

通过调用resultFn函数即可得到如下结果
在这里插入图片描述

(2)两个函数及以上返回值依次调用

修改后参照代码如下:

methods:{
   testOne(){
      return new Promise((resolve,reject) =>{
        setTimeout(function () { //模拟异步操作,延时函数可以换成你需要的axios或者ajax请求
         resolve('我是第一个函数的返回值')
        },500)
      })
    },
    testTwo(data){
      return new Promise((resolve,reject) =>{
        console.log('data值为:'+data)
        setTimeout(function () { //模拟异步操作,得到data数据,执行下一步处理,延时函数可以换成你需要的axios或者ajax请求
          console.log('我是第二个函数的返回值')
          resolve('我是第二个函数的返回值')
        },500)
      })
    },
    resultFn(){
       this.testOne().then(res1 =>{
        console.log(res1)
        console.log('得到res执行下一步操作')
        this.testTwo(res1).then(res2 =>{
          console.log(res2)
          console.log('得到res2执行下一步操作')
        })
      })
    },
}

通过调用resultFn函数即可得到如下结果,多个即可同理逻辑
在这里插入图片描述

(3)某个函数需要多个异步函数的返回值

通过promise.all([p1,p2]).then(),将多个Promise实例,包装成一个新的Promise实例,返回值为多个promise返回值组成的一个数组。
参照代码如下:

methods:{
   testOne(){
      return new Promise((resolve,reject) =>{
        setTimeout(function () { //模拟异步操作,延时函数可以换成你需要的axios或者ajax请求
          // console.log('我是第一个函数的返回值')
          resolve('返回值为1')
        },500)
      })
    },
    testTwo(){
      return new Promise((resolve,reject) =>{
        setTimeout(function () { //模拟异步操作,延时函数可以换成你需要的axios或者ajax请求
          resolve('返回值为2')
        },500)
      })
    },
    resultFn(){
     Promise.all([this.testOne(),this.testTwo()]).then((result) => {
        console.log(result)
        console.log("执行完毕");
      })
    },
}

通过调用resultFn函数即可得到如下结果
在这里插入图片描述

2.循环异步函数同步化处理

通常可能会得到一个数组集合,循环调用某个接口,对该数组进行处理,我们需要等到该数组循环处理完毕之后或者页面渲染完毕之后,再对该新数组进行下一步的操作。这个需要用到es7语法asyncawait的使用。
async这里不做过多描述,可参照该网站理解:async函数

Async await注意事项

  1. await 只能出现在 async 函数中。
  2. await等待一个返回值,可以是promise对象,也可以是任意表达式的结果,要想阻塞后面的代码, await后面的异步操作必须返回一个promise实例(我在这里踩了坑),通过resolve得到结果才执行后面的代码。否则尽管该行代码是异步,await依然不会在该处停留等待异步操作完成,可以说await是依赖promise判断该异步操作是否执行结束的。
  3. async/await同样可解析出promise实例化对象,不需要通过调用then()取其返回值。直接调用let data=await this.testOne()同时搭配async的使用,data就是该函数的具体返回值。
    4.循环调用接口时用for循环,不要用forEach,forEach搭配await阻塞不了异步线程。
    代码如下(示例):
methods:{
   testOne(){
     return new Promise(resolve => {
       setTimeout(function () { //模拟异步操作操作得到一个res返回值
         let res=[
           {
           name:'limoumou',
           age:'23'
         },
           {
             name:'limoumou',
             age:'24'
           }
           ]
         console.log('旧数据data为:',res)
         resolve(res) //模拟res数据
       },500)
     })
    },
    async testTwo(){
       for (let item of this.arr) {
         await new Promise((resolve,reject) =>{
         setTimeout(function () { //模拟异步操作,延时函数可以换成你需要的axios或者ajax请求
           let arr='1'
           item.test=arr  //模拟异步请求的数据对该数组进行改造
           resolve()
         },1000)
         })
       }
       console.log('新数据data为:',data);
       console.log('下一步对该数组的操作');
    },
    resultFn(){
         this.testOne().then(res =>{
             console.log(res)
             this.testTwo(res).then(res1 =>{
         })
      })
    },
}

通过调用resultFn函数即可得到如下结果
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐