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 中的拒绝值(拒绝原因)。

  • 相关阅读:
    现代软件工程 第一章 概论 第4题——邓琨
    现代软件工程 第一章 概论 第9题——邓琨
    现代软件工程 第一章 概论 第7题——张星星
    现代软件工程 第一章 概论 第5题——韩婧
    hdu 5821 Ball 贪心(多校)
    hdu 1074 Doing Homework 状压dp
    hdu 1074 Doing Homework 状压dp
    hdu 1069 Monkey and Banana LIS变形
    最长上升子序列的初步学习
    hdu 1024 Max Sum Plus Plus(m段最大子列和)
  • 原文地址:https://www.cnblogs.com/94pm/p/9650418.html
Copyright © 2011-2022 走看看