我们先不讲Promise A+ 规范理论,先看一道面试题:
var promise=new Promise((resolve,reject)=>{reject();})
promise.then(null,function(){
return '大湿老凯'
})
.then('举个','栗子')
.then('看起来','很简单')
.then(()=>{
console.log('promise 已完成');
},()=>{
console.log('promise 已拒绝');
})
那么大家告诉我,这道题的结果是啥?
1.说出答案前,首先我们回顾下什么是Promise?
Promise是JS异步编程中的重要概念,异步抽象处理对象是目前比较流行Javascript异步编程解决方案之一。
2.为什么我们需要Promise?
-
javascript是一门单线程语言,早期我们解决异步的场景时,大部分情况下是通过回调函数进行。当前除了回调函数,我们还有事件监听、发布/订阅的方式来解决。
-
对于回调函数来说,我们都知道以嵌套方式来解决会形成 "回调地狱",比如下面这个例子。
function a(functionb(){
c(function d(){
})
})
这样一来,在处理越多的异步逻辑时,就需要越深的回调嵌套,这种编码模式的问题主要有以下几个:
-
代码逻辑书写顺序与执行顺序不一致,不利于阅读与维护,甚至于很混乱。
-
异步操作的顺序变更时,需要大规模的代码重构。
-
回调函数基本都是匿名函数,bug 追踪困难。
-
回调函数是被第三方库代码(如上例中的 ajax )而非自己的业务代码所调用的,造成了 IoC 控制反转。
3. 那么如何使用Promise来解决上述的问题呢?
-
在支持ES6的高级浏览器环境中,我们过new Promise()来构造一个promise实例,接收一个excutor执行函数作为参数, excutor有两个函数类型形参,分别是resolve和reject。
-
Promise
有三种状态:pending/reslove/reject ,pending就是未决,resolve可以理解为成功,reject可以理解为拒绝。
我们看一个最简单的形式:
let promise = new Promise((resolve, reject) => {
//模拟异步
setTimeout(()=>{
resolve('prom')
},1000)
})
var onResolve=function(val){
console.log('已完成,{}',val);
}
var onReject=function(val){
console.log('已拒绝,{}',val);
}
//第一个参数为resolve后执行,第二个参数为reject后执行
promise.then(onResolve,onReject);
//也可以通过.catch方法将状态变为已拒绝的promise拦截
promise.then(onResolve).catch(onReject);
//还可以通过try catch将状态变为已拒绝的promise拦截
try{
promise.then(onResolve)
}catch(e){
onReject(e);
}
通过promise对象,我们可以基本解决优雅回调的问题。
回到开头那一道面试题,我们如果不了解Promise的规范,还是无法从原理的层面快速做出来。
4.接下来我们看下Promise A+规范
任何符合promise规范的对象或者函数都可以成为promise。
Promise A+规范很长,我这里就不贴在文章里了。大家可以自己查找规范英文原文:https://promisesaplus.com/,
不懂的同学,我给搜了一篇中文版的 https://www.icode9.com/content-4-365156.html。
规范里有非常重要的几条,可以帮助我们解决这道面试题:
1.then 方法可以被同一个 promise 调用多次,当 promise 成功执行时,所有 onFulfilled 需按照其注册顺序依次回调;当 promise 被拒绝执行时,所有的 onRejected 需按照其注册顺序依次回调。
var promise=new Promise((resolve,reject)=>{reject();})
这里promise返回了reject()拒绝执行,那么很显然,后续将会调用一下onReject()函数
function(){return '大湿老凯'}
2.只要 onFulfilled 或者 onRejected 返回一个值 x ,promise2都会进入onFulfilled 状态 。
如果 onFulfilled
不是函数,其必须被忽略,如果 onRejected
不是函数,其必须被忽略。
所以,以下两个then都会被忽略,'大湿老凯'使得最后的.then进入onFulfilled 状态。
.then('举个','栗子')
.then('看起来','很简单')
最终会打印“promise 已完成”。
console.log('promise 已完成');
学无止境,觉得不错的话,请关注前端琅琊阁de 微信公众号和头条号!