当前位置:网站首页>Promise异步编程

Promise异步编程

2022-07-01 08:43:00 深海蓝山

目录

一、回调函数本身是同步代码

二、Promise介绍

1. Promise结构

2. Promise的三种状态:

3. Promise的链式调用

 三、Promise的注意事项

 1. 链式调用 

2. Promise中断 

四、Promise常用的Api 

1. Promise.all()

 2.Promise.race()

五、Async和Await


一、回调函数

回调函数本身是同步代码

通常在编写JavaScript代码时,使用的回调嵌套的形式大多是异步函数,所以会导致部分开发者认为凡是回调形式的函数都是异步流程。其实并不是这样的,真正的解释是:JavaScript中的回调函数结构,默认是同步的结构,由于JavaScript单线程异步模型的规则,如果想要编写异步的代码,必须使用回调嵌套的形式才能实现,所以回调函数结构不一定是异步代码,但是异步代码一定是回调函数结构。

二、Promise介绍

注意:Promise是同步方法,promise.then是异步方法 

 console.log('--开始----');
        const p = new Promise(function(resolve, reject) {
        console.log('调用Promise');
        // resolve可以触发then中的回调执行
        resolve('执行了resolve');
        // reject('异常了');
      });
      p.then(res => {
        console.log('then 执行', res);
      })
        .catch(err => {
          console.log('catch 执行', err);
        })
        .finally(() => {
          console.log('finally 执行');
        });
      console.log('--结束----');
	  
	  执行结果:
      --开始----
      调用Promise
      --结束----
      then 执行 执行了resolve
      finally 执行

 通过上例,我们可以知道new Promise中的回调函数确实是在同步任务中执行的,其次是如果这个回调函数内部没有执行resolve或者reject那么p对象后面的回调函数内部都不会有输出,而运行resolve函数之后.then和.finally就会执行,运行了reject之后,catch和finally就会执行

1. Promise结构

每一个Promise对象都包含三部分

  1. [[Prototype]]: 代表Promise的原型对象
  2. [[PromiseState]]: 代表Promise对象当前状态
  3. [[PromiseResult]]: 代表Promise对象的值,分别对应resolve或reject传入的结果

2. Promise的三种状态:

  • pending:初始状态,也叫就绪状态,这是在Promise对象定义初期的状态,这时Promise仅仅做了初始化并注册了他对象上所有的任务。
  • fulfilled:已完成,通常代表成功执行了某一任务,当初始化中的resolve执行时,Promise的状态就变更为fulfilled,并且then函数注册的回调函数会开始执行,resolve中传递的参数会进入回调函数作为形参。
  • rejected:已拒绝,通常代表执行了一次失败任务,或者流程中断,当调用reject函数时,catch注册的回调函数就会触发,并且reject中传递的内容会变成回调函数的形参。

3. Promise的链式调用

链式调用的本质就是在调用这些支持链式调用的函数的结尾时,又返回了一个包含他自己的对象或一个新的自己,这些方式都可以实现链式调用。

     // 链式调用
      function MyPromise() {
        return this;
      }
      MyPromise.prototype.then = function() {
        console.log('触发了then');
        return this;
      };
      new MyPromise().then().then();

 三、Promise的注意事项

 1. 链式调用 

// 链式调用的注意事项
      let pr = new Promise((resolve, reject) => {
        resolve('promise实例');
      });
      pr.then(res => {
        console.log('res'); // undefined
        return '123';
      })
        .then(res => {
          console.log('res'); // 123
          return new Promise(resolve => {
            resolve(456);
          });
        })
        .then(res => {
          console.log('res'); // 456
          return '直接返回的结果';
        })
        .then()
        .then('字符串')
        .then(res => {
          console.log('res'); // 直接返回的结果
        });

 

1、只要有then()并且触发了resolve,整个链条就会执行到结尾,这个过程中的第一个回调函数的参数是resolve传入的值

2、后续每个函数都可以使用retrun返回一个结果,如果没有返回结果的话,下一个then中回调函数的参数就是undefined

3、返回结果如果是普通变量,那么这个值就是一个then中回调函数的参数

4、如果返回的是一个Promise对象,那么这个Promise对象resolve的结果会变成下一次then中回调的函数的参数【直接理解为,返回Promise对象时,下一个then就是该对象的then】

5、如果then中传入的不是函数或者未传值 ,Promise链条并不会中断then的链式调用,并且在这之前最后一次的返回结果,会直接进入离它最近的正确的then中的回调函数作为参数

2. Promise中断 

有两种形式[throw/reject]可以让then的链条中断,如果中断还会触发一次catch的执行。 

// 链式调用的中断
      let pe = new Promise((resolve, reject) => {
        resolve('Promise的值');
      });
      pe.then(res => {
        console.log(res);
      })
        .then(res => {
          // 两种方式中断Promise
          // throw '通过throw中断';
          return Promise.reject('reject中断');
        })
        .then(res => {
          console.log(res);
        }).catch(res => {
          console.log('catch执行', res);
        });;

四、Promise常用的Api 

1. Promise.all()

当我们在代码中需要使用异步流程控制时,可以通过Promise.then来实现让异步流程一个接一个的执行,假设有三个接口,并保证三个接口的数据全部返回后,才能渲染页面。如果a耗时1s、b耗时0.8s、c接口耗时1.4s,如果用Promise.then来执行流程控制,如果通过then函数的异步控制,必须等待每个接口调用完毕才能调用下一个,这样总耗时就是 1+0.8+1.4=3.2s。这种累加显然增加了接口调用的时间消耗,所以Promise提供了一个all方法来解决这个问题:

Promise.all([promise对象,promise对象,...]).then(回调函数)

回调函数的参数是一个数组,按照第一个参数的promise对象的顺序展示每个promise的返回结果。

借助Promise.all来实现,等最慢的接口返回数据后,一起得到所有接口的数据,那么这个耗时将会只按照最慢接口的消耗时间1.4s执行,总共节省了1.8s.

Promilse.all相当于统一处理了多个promise任务,保证处理的这些所有promise对象的状态全部变成为fulfilled之后才会触发all的.then函数来保证将放置在all中的所有任务的结果返回

 2.Promise.race()

Promise.race([promise对象,promise对象,...]).then(回调函数)

回调函数的参数是前面数组中最快一个执行完毕的promise的返回值。

Promilse.race()相当于将传入的所有任务进行了一个竞争,他们之间最先将状态变成fulfilled的那一个任务就会直接的触发race的.then函数并且将他的值返回,主要手于多个任务之间竞争时使用

五、Async和Await

async和await相当于使用了自带执行函数的Generator函数,所以async和await逐渐成为主流异步流程控制的终极解决方案。

  async handleTest() {
      console.log('1');
      // this.test();// await方法
      this.promisTest(); // 等价promise方法
      console.log('2');
      // 输出顺序:1,3,2,4
    },
    // await方法
    async test() {
      console.log(3);
      var a = await 4;
      console.log(a);
    },
    // 此方法是test方法的promsise写法
    promisTest() {
      new Promise(resolve => {
        console.log(3);
        resolve(4);
      }).then(res => {
        console.log(res);
      });
    }

 async函数中有一个最大的特点,就是第一个await会作为分水岭一般的存在,在第一个await的右侧和上面的代码,全部是同步代码区域相当于new Promise的回调,第一个await的左侧和下面的代码,就变成了异步代码区域相当于then的回调。

 

 

原网站

版权声明
本文为[深海蓝山]所创,转载请带上原文链接,感谢
https://luqinghua.blog.csdn.net/article/details/125244540