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

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

猜你喜欢

转载自www.cnblogs.com/94pm/p/es6.html