异步编程是JS的一个重要特性,但是过度依赖回调函数就会造成“回调地狱”。Promise的出现就是为了解决这个问题,让异步代码变得更加清晰易读。Promise是JS中进行异步编程的一种解决方案,它是由异步操作最终完成或者失败而决定的对象。它有三种状态:
- Pending:初始状态。
- Fulfilled:操作成功完成。
- Rejected:操作失败。一旦Promise状态变为Fulfilled或Rejected,它就会保持这个状态,不会再变。一个Promise构造函数接收一个执行器函数作为参数,执行器函数有两个参数:resolve和reject。分别对应Promise对象的Fulfilled状态和Rejected状态。
js
const promise = new Promise((resolve, reject) => {
// 执行异步操作
if (/* 异步操作成功 */) {
resolve('Success!')
} else {
reject(new Error('Failed!'))
}
})
Promise实例生成以后,可以用then方法分别指定Fulfilled状态和Rejected状态的回调函数。
js
promise.then(value => {
// 获得Fulfilled状态的结果
}, reason => {
// 获得Rejected状态的结果
})
还可以使用catch方法指定Rejected状态的回调函数。
js
promise.catch(reason => {
// 捕获Rejected状态的结果
})
Promise 可以像信使一样一边读取回调数据一边向后传达数据。这在很大程度上修复了“回调地狱”的问题。总之,Promise把异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。这使得异步代码更加容易理解和阅读。
这里继续扩展一些Promise的知识点:Promise的链式调用Promise对象的then方法返回的是一个新的Promise对象,这样就可以实现Promise的链式调用,从而避免层层嵌套的回调函数。
js
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.catch(error => console.log(error))
如果一个Promise链中有一个Promise被Rejected,那么所有的Promise都会被Rejected,并执行最后的catch方法。Promise静态方法Promise提供了三个静态方法:
- Promise.resolve():将现有对象转为Promise对象,如果参数是Promise实例本身,则直接返回这个实例。
- Promise.reject():返回一个状态为Rejected的Promise对象。
- Promise.all():接收一个Promise对象数组作为参数,当所有Promise都Fulfilled时返回Fulfilled状态,并把所有Promise的结果作为数组返回;如果有一个被Rejected,则直接返回Rejected状态。例如:
js
const p1 = Promise.resolve('Success')
const p2 = Promise.reject('Failed')
Promise.all([p1, p2]).then(res => console.log(res))
// 不会执行
Promise.all([p1, p2]).catch(err => console.log(err))
// Failed
Promise的状态一经改变就不会再变Promise的状态改变只有两种可能:由Pending变为Fulfilled或由Pending变为Rejected。一旦状态改变,Promise的实例原始值就不会再被修改。所以,不管你之后如何改变Promise的值,它的状态是不会改变的。这就是Promise的不变性(promise immutability)。基于上述这些知识点,我们就可以很好的运用Promise进行异步编程了。Promise大大简化了回调的嵌套结构,使异步代码变得更清晰和易于理解。