# Promise

7 min read
Table of Contents

Promise 对象表示异步操作的最终完成(或失败)及其结果值。

Promise 在创建的时候并不知道最终的值,这使得异步方法像同步方法一样返回值,异步方法没有立即返回最终值,而是返回一个在未来使用的 promise 值。

三种状态

Promise 有三种状态:pending(待定),fulfilled(完成),rejected(拒绝)。

  1. 当 pending 时,promise 可能切换到 fulfilled 或者 rejected 状态的值。
  2. 当 fulfilled 时,promise 无法切换到其他状态,且必须有一个不变的 value。
  3. 当 rejected 时,promise 无法切换到其他状态,且必须有一个不变的 reason。
promise

实例方法

then

Promise 最重要的方式就是 then 方法,该方法注册了回调,用以接受 Promise 的最终值或 Promise 拒绝的原因。

Promise.prototype.then 方法返回一个新的 Promise 实例,并接收两个参数 onFulfilled(可选),onRejected(可选)。

p.then(onFulfilled[, onRejected]);
p.then(value => {
// fulfillment
}, reason => {
// rejection
});

catch

Promise.prototype.catch 方法返回一个新的 Promise 实例。catch 方法等同于 then 方法的 onRejected。

p.catch(onRejected)
p.catch(function (reason) {
// rejection
})

finally

Promise.prototype.finally 方法不管 Promise 状态如何都会执行,该方法的回调函数不接受任何参数。

p.finally(function () {
// settled (fulfilled or rejected)
})

链式调用

在多个 Promise 调用的时候,可以通过扁平化的链式调用代替嵌套式的调用,这样可以更加简洁,清晰,易于理解。

// 嵌套式调用
promise1()
.then(function (result) {
promise2(result)
.then(function (newResult) {
promise3(newResult)
.then(function (finalResult) {
console.log(`Got the final result: ${finalResult}`)
})
.catch(failureCallback)
})
.catch(failureCallback)
})
.catch(failureCallback)

在嵌套式调用的时候,每个 Promise 写在一个 .then() 里,类似于递归的回调地狱。而在扁平化的链式调用中,每个 Promise 写在一个连续的 then() 里,每个 then() 方法接受返回下个 Promise 函数。

// 扁平化的链式调用,与上面的嵌套式调用等价
promise1()
.then(function (result) {
return promise2(result)
})
.then(function (newResult) {
return promise3(newResult)
})
.then(function (finalResult) {
console.log(`Got the final result: ${finalResult}`)
})
.catch(failureCallback)
// 使用箭头函数省略 return
promise1()
.then((result) => promise2(result))
.then((newResult) => promise3(newResult))
.then((finalResult) => console.log(`Got the final result: ${finalResult}`))
.catch(failureCallback)

静态方法

Promise.all

Promise.all([..]) 方法接受一个 Promise 对象数组作为参数。当数组内全部的 Promise 对象成功才会返回一个数组,而失败的时候则返回最先被 reject 状态的值。

Promise.all(iterable)

一个例子:

const p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo')
})
const p2 = Promise.resolve(3)
const p3 = 42
const p4 = Promise.reject('bar')
Promise.all([p1, p2, p3]).then((values) => {
console.log(values)
}) // => ["foo", 3, 42]
Promise.all([p1, p2, p3, p4]).catch((reject) => {
console.log(reject)
}) // => bar

Promise.allSettled

Promise.allSettled([..]) 方法接受一个 Promise 对象数组作为参数。当数组内全部的 Promise 对象完成或失败才会返回一个数组,每个数组项的状态和值都是一个对象。

Promise.allSettled 是为了解决 Promise.all 的缺陷,Promise.all 的缺陷是只有全部的 Promise 对象都成功了才会返回结果。如果有任意一个 Promise 对象失败了,那么都会进入 catch 异常。

const p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo')
})
const p2 = Promise.resolve(3)
const p3 = 42
const p4 = Promise.reject('bar')
Promise.allSettled([p1, p2, p3, p4]).then((values) => {
console.log(values)
})
// [
// { status: 'fulfilled', value: 'foo' },
// { status: 'fulfilled', value: 3 },
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: 'bar' },
// ];

Promise.race

Promise.race([..]) 参数中的实例最先改变状态,就会立即将该实例的返回值作为 Promise.race([..]) 方法的返回值。

const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one')
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two')
})
Promise.race([promise1, promise2]).then((value) => {
console.log(value) // two, 都是完成状态,但是第二个会更快
})

Promise.any

Promise.any([..]) 返回输入中最先成功的 Promise,如果所有的 Promise 都失败,则返回一个 AggregateError 对象。

Promise.any([..]) 跟 Promise.race([..]) 类似,只不过只会接受第一个成功的返回值,而不像 Promise.race([..]) 那样,会接受 reject 状态的返回值。

const promise1 = Promise.reject(0)
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'quick'))
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, 'slow'))
const promises = [promise1, promise2, promise3]
Promise.any(promises).then((value) => console.log(value)) // quick,0 会被忽略

Promise.resolve

Promise.resolve() 将现有对象转为 Promise 对象。

如果该方法的参数为一个 Promise 对象,则直接返回;如果参数 thenable 对象(即具有 then 方法),Promise.resolve() 将该对象转为 Promise 对象并立即执行 then 方法;如果参数是一个原始值,或者是一个不具有 then 方法的对象,则 Promise.resolve 方法返回一个新的 Promise 对象,状态为 fulfilled,其参数将会作为 then 方法中 onResolved 回调函数的参数,如果 Promise.resolve 方法不带参数,会直接返回一个 fulfilled 状态的 Promise 对象。

需要注意的是,立即 resolve() 的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。

Promise.reject

Promise.reject() 同样返回一个新的 Promise 对象,状态为 rejected,无论传入任何参数都将作为 reject() 的参数

参考链接


More Posts

# BFC

8 min read

BFC(Block Formatting Context) 块级格式化上下文。它是块级布局发生的区域,也是浮动与其他元素交互的区域。