一、什么是Promise
没想一下这样一个场景:我走到快餐店的柜台,点了一个芝士汉堡,我交给收银员14元。通过下订单并付款,我已经发出了一个对某个值 (就是那个汉堡),的请求。我已经启动了一次交易。但是,通常我不能马上就得到这个汉堡。收银员会交给我某个东西来代替汉堡:一张带有订单号的收据。订单号就是一个承诺 (promise),保证了最终我会得到我的汉堡。
上面这个例子来自 《你不知道的JavaScript》 ,不难看出Promise确保了我们最终能得到一个悬而未决的事情的结果。光说可能有点抽象,那么我们可以通过代码中的具体例子来说明。
1.1 回调地狱
setTimeout(() => {
// 1层回调
console.log("延迟1秒后输出");
setTimeout(() => {
// 2层回调
console.log("延迟2秒后输出");
setTimeout(() => {
// 3层回调
console.log("延迟3秒后输出");
}, 3000);
}, 2000);
}, 1000);
以上这段代码第一层setTimeout的回调函数中嵌套了第二层setTimeout,而第二层的回调函数又嵌套了第三层setTimeout,这样的层层嵌套会让代码变得不易阅读、难以维护。这种回调函数里面嵌套回调函数的写法,就叫做回调地狱
1.2 如何解决
我们希望能有一种代码组合方式,在确保拿到上一次回调结果并对其进行处理的同时,避免回调地狱引起代码的不断缩进,链式调用是一种很好地解决方式。
doSomething(args).then((result)=>{
//continue to do something
return res
}).then((result)=>{
//continue to do something
return res
}).then((result)=>{
//continue to do something
})
以上这段代码中then的回调函数接受了上一次函数调用的返回结果,进行处理后可以将结果继续返回交给下一层then继续处理,代码的简洁性和可读性较之前均有了明显的提升。
1.3 简单介绍
我们今天的主角promise,就是这样一个可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果,并且可以在对象之间传递和操作数据,处理队列的一种异步编程的解决方案。
二、Promise的创建
现在我们正式进入对promise的使用阶段。
2.1 Promise的constructor
let promise = new Promise((resolve, reject) {
// executor(生产者代码,比如load资源)
});
- new Promise接受一个函数作为参数,这个函数被称为executor,当new Promise被创建,executor就会自动执行。
- 这个函数的参数 resolve 和 reject,作为任务完成或失败后的回调函数:
- resolve(value):如果完成了任务,就如此调用resolve,它会返回成功的value;
- reject(reason):如果因为任何原因未完成任务,就如此调用reject,它会带上失败的reason。
2.2 Promise的状态变化
new Promise构造器返回的promise对象,具有如下三个状态(state):
- pendding(等待态)
- rejected(失败态)
- fullfilled(成功态)
值得注意的是,状态一旦改变就不会再次变化,就是说一旦promise对象的状态从pendding变为rejected或者fullfilled后无论怎么进行后续操作,状态都不会回到pendding。
2.3 Promise的实例方法
创建Promise实例对象
const p = new Promise((resolve,reject)=>{
if("异步请求成功"){
resolve('成功的结果')
}else{
reject('失败的信息')
}
});
- then方法
then接受两个函数分别作为resolve/reject后的回调函数。
p.then(
(res)=>{
//执行resolve则进入此函数
console.log(res) //成功的结果
},
(err)=>{
//执行reject则进入此函数
console.log(err) //失败的信息
}
)
- catch方法
catch接受一个函数作为reject或者抛出错误后的回调函数。
注:catch实际上是then(undefined,(err)=>{})的语法糖,等价于不传入resolve的回调函数只传入reject的回调函数。
p.catch(
//捕获错误
//reject或throw一个error后会被catch捕获
(err)=>{
console.log(err) //错误的信息
}
)
- finally方法
finally接受一个函数作为最后必定执行的回调函数。
注:finally将result或者error直接传递给下一个处理程序,而不是像then那样自己返回一个thenable对象。
p.then(
(res)=>{
//执行resolve则进入此函数
console.log(res) //成功的结果
}
).catch(
//捕获错误
//reject或throw一个error后会被catch捕获
(err)=>{
console.log(err) //错误的信息
}
).finally(
(finally)=>{
console.log(finally) //最后必定执行的代码
}
)
以上就是Promise的基本介绍和三个实例方法的说明。