zoukankan      html  css  js  c++  java
  • Promise关键知识

    异步是ES6中使用频率最高的特性之一,也是面试中经常会被问到的问题,特此整理了相应的笔记

    一、Promise的三种状态

    pending-异步操作没有结束

    fulfilled-异步操作已成功结束,最常见的就是在promise对象中返回resolve()

    rejected-异步操作未成功,可能是有错误等,最常见的就是在promise对象中返回reject()

    二、Promise的几大特性

    1.立即执行特性

    当实例化了一个Promise对象时,作为Promise参数传入的函数是会被立即执行的,只是其中执行的代码可以是异步代码。

    特别需要注意的是,不能理解为调用.then()时Promise参数中的函数代码才开始执行

    var p = new Promise(function(resolve, reject){
     console.log("create a promise"); 
     resolve("success");
    });
     
    p.then(function(value){
     console.log(value);
    });
    console.log("after new Promise"); 

     控制台输出结果

    "create a promise"
    "after new Promise"
    "success"
    2.then()方法中的回调函数是异步执行的
    在上面的代码中console.log("after new Promise"); 虽然是在.then()方法后面调用,但是却先执行了,说明了then()的回调函数是异步执行的,需要等同步代码执行完了才会执行。
    3.状态不可逆
    当一个Promise对象的状态变为fulfilled或rejected后再改变状态是无效的
    var p2 = new Promise(function(resolve, reject){
     resolve("success");
     resolve("suceess2");
    });
    p2.then(function(value){
     console.log(value);
    });

     控制台输出的结果是sucess而不是sucess2

    4.链式调用

    • Promise对象出现的目的就是避免回调嵌套,避免回调嵌套的手段就是使用链式调用。链式调用的实现原理实现中很简单,就是在每个方法中返回一个相同类型的对象。
    • 不管是then()还是catch,不管使不使用return最终都会返回一个新的Promise实例。
    • 没有return时默认返回一个状态为fulfilled的对象,如果在then中抛出异常则返回一个rejected状态的对象;
    • 使用return时可以返回一个指定状态的Promise实例,也可以返回为普通值,当返回的是普通值时,实际上JS引擎会进行包装
    var p = new Promise(function(resolve, reject){
     resolve(1);
    });
    p.then(function(value){ //第一个then
     console.log(value);
     return value*2;
    }).then(function(value){ //第二个then
     console.log(value);
    }).then(function(value){ //第三个then
     console.log(value);
     return Promise.resolve('resolve'); 
    }).then(function(value){ //第四个then
     console.log(value);
     return Promise.reject('reject');
    }).then(function(value){ //第五个then
     console.log('resolve: '+ value);
    }, function(err){
     console.log('reject: ' + err);
    })
    •  then中的Promise,必须在then内部再次使用then或catch进行处理,不然外层的then或catch无法捕获到状态
      var p = new Promise(function(resolve, reject){
          setTimeout(resolve('我是在then里调用的'),50)
      });
      var p2=function(){
          return new Promise(function(resolve, reject){
              setTimeout(resolve('放在第一个then中执行'),50)
          });
      }
      p.then(function(value){
         console.log('第一个then')
         p2()
      })
      .then(()=>{
          console.log('第二个then语句')
      })
      .catch((e)=>{
          console.log(e)
      })

    上面的代码在p的第一个then中又调用了一个Promise-p2,此时p2没有没用then()或catch(),因此该then方法直接把控制权转给了后面的then或catch,控制台输出的结果如下

    ---第一个then

    ---第二个then

    当我们把p2()改成p2().then((e)=>console.log(e))时,最外面一层的第二个then会进行等待:

    ---第一个then

    ---放在第一个then中执行

    ---第二个then

    三、resolve和reject中的返回值是Promise类型对象时的处理机制

    既可以在执行器中使用resolve(xxx)和reject(xxx),也可以使用Promise.resolve(xxx)和Promise.reject(xxx)来返回对象的执行状态,如果返回值是一个Promise类型的对象时情况比较有趣。

    如果xxx是一个Promise类型,resolve(xxx)或Promise.resolve(xxx)会等待xxx的执行状态,并把XXX返回的状态做为对象的最终状态。

    var p2 = new Promise(function(resolve, reject){
     resolve(Promise.reject('reject')); //resolve中是一个执行失败的状态,因此p2的状态为rejected
    });
    p2.catch((err)=>console.log(err))

    reject(xxx)或Promise.reject(xxx)则相对简单粗暴,直接把对象的状态变为rejected,不会根据XXX的执行结果来改变自身状态

    var p2 = new Promise(function(resolve, reject){
     reject(Promise.resolve('resolve')); 
    });
    p2.catch((e)=>{
        console.log(e)
    })
    var p3=Promise.reject(Promise.resolve('成功状态'))
    p3.catch((e)=>{
        console.log(e)
    })

    四、Promise中的错误

    1.既可以使用throw语句,也可以使用reject,代码如下:

    var p = new Promise(function(resolve, reject){
       throw new Error('显示抛出一个错误')
       //上面的代码等同于
       try{
          throw new Error('显示抛出一个错误')
       }
       catch(ex){
           reject(ex)
       }
    });

    2.抛出的错误可以使用then(null,(err)=>{...})也可以使用.catch((err)=>{})来捕获,当使用链式调用时,后面的catch可以捕获前面的错误

    var p = new Promise(function(resolve, reject){
       throw new Error('显示抛出一个错误')
    });
    //异常处理
    p.then(null,function(err){
     console.log(err.message);
     return Promise.reject('返回一个reject')
    })
    .catch((err)=>{console.log(err)})

     3.es2018新增了.finally(),不管Promise实例最终返回什么状态,都可以被该方法捕获到

    promise
    .then(result => {···})
    .catch(error => {···})
    .finally(() => {···});

    4.错误处理钩子

    未使用上面的错误处理机制时,可以监听unhandledrejection事件和rejectionhandled事件来获取错误

    unhandledRejection :当一个 Promise 被拒绝、而在事件循环的一个轮次中没有任何拒 绝处理函数被调用,该事件就会被触发;

    rejectionHandled :若一个 Promise 被拒绝、并在事件循环的一个轮次之后再有拒绝处 理函数被调用,该事件就会被触发。

    在node.js中使用process.on('xxxx', (reason, promise) => ···)来监听事件,在window中使用window.addEventListener('unhandledrejection', event =>...),浏览器的event对象有三个属性

    type :      事件的名称( "unhandledrejection" 或 "rejectionhandled" );
    promise :被拒绝的 Promise 对象;
    reason :  Promise 中的拒绝值(拒绝原因)。

  • 相关阅读:
    Java面試題(实用性高)
    索引的概述?
    给Eclipse提速的7个技巧
    ETL数据仓库
    实用SQL语句大全
    考证
    PL/SQL 程序
    eclipse
    httpd.conf详解,因为php始终报fileinfo扩展无法加载的错
    dockerfile创建镜像及容器
  • 原文地址:https://www.cnblogs.com/94pm/p/9650418.html
Copyright © 2011-2022 走看看