Promise关键知识

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

一、Promise的三种状态

pending-异步操作没有结束

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

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

二、Promise的几大特性

1.构造函数立即执行特性

当实例化了一个Promise对象时,作为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.状态不可逆
当一个Promise对象的状态变为fulfilled或rejected后再改变状态是无效的
var p2 = new Promise(function(resolve, reject){
 resolve("success");
 resolve("suceess2");
});
p2.then(function(value){
 console.log(value);
});

 

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

3.链式调用

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

三、返回promise结果的方式

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

当一个promise需要resolve的数据是异步对象时,会先等待该异步对象的结果,如果结果为rejected,即使使用resolve(),实际上还是返回rejected

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中的错误

抛出的错误可以使用then(null,(err)=>{...})也可以使用.catch((err)=>{})来捕获,当使用链式调用时,后面的catch可以捕获前面的错误,要这个异常没有被链条中的前一个 .catch().then() 处理掉

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

 

posted @ 2018-09-15 17:45  我是格鲁特  阅读(231)  评论(0)    收藏  举报