聊聊 Promise
Promise相信写前端的同学都不陌生,本意是承诺,答应完成某事。promise主要用于异步计算。可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。还可以在对象之间传递和操作promise,帮助我们处理队列。
和其他异步调用的优点在于:
promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)。
并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据。
代码风格,容易理解,便于维护。
多个异步等待合并便于解决。
promise有三个状态:
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
promise状态一经改变,不会再变。
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled
从pending变为rejected。
这两种情况只要发生,状态就凝固了,不会再变了。
所以我们可以生成这样的链式调用 new Promise().then().then().catch()
我们来看下Promise可以怎么处理异常:
第一种catch+then
//catch+then
new Promise(resolve => {
throw new Error('this is a error')
}).catch(err=>{
console.error('catch+then: I catch',err)
}).then(res=>{
console.log('222')
}).catch(err=>{
console.error('catch+then: I catch2',err)
})
image.png
可以看出catch返回的Promise的状态也是resolved,可以继续执行then。
第二种 then
//then
new Promise(()=>{
console.log('start...')
throw new Error('this is a error')
}).catch(err=>{
console.error('i catch:', err)
throw new Error('this is another error')
}).then(()=>{
console.log('test')
}).then(()=>{
console.log('test2')
}).catch(err=>{
console.error('I also catch ',err)
})
image.png
可以看出抛出错误变为rejected状态,所以绕过两个then直接跑到最下面的catch。
Promise.all(p1,p2...),等待p1,p2 都完成了返回。
Promise.race(p1,p2,..),只要有一个完成,就返回。
可用于异步操作和定时器放在一起,如果定时器先触发,就认为超时,告知用户;
接下来,我们来挑战下Promise经典的四道题:
1. doSomething().then(function () {
return doSomethingElse();
});
2. doSomething().then(function () {
doSomethingElse();
}).then(final);
3. doSomething().then(doSomethingElse()).then(final);
4. doSomething().then(doSomethingElse);
第一个:先执行doSomething(),然后再执行doSomethingElse(),然后再往下执行。
第二个:没有return,所以函数体中不返回新的promise实例,所以是两个队列,在doSomething执行完后,final和doSomethingElse同时执行。
第三个:函数体中是doSomethingElse(),是一个可执行的promise实例,可以和doSomething一起执行,然后它的结束状态不管,final函数会在doSomething结束后执行。
第四个:跟平时见到的一样,resolve和reject,按顺序执行。
综上,Promise感觉和java中的builder构造器一样,又有点像适配器模式那样,将复杂的请求分而治之,无疑是前端开发的一大利器。
发表评论 (审核通过后显示评论):