Promise

21 阅读3分钟

描述

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

状态

  • 待定(pending) :初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled) :意味着操作成功完成。
  • 已拒绝(rejected) :意味着操作失败。

如果一个 Promise 已经被兑现或拒绝,即不再处于待定状态,那么则称之为已敲定(settled)

image.png

const promise = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('success')
    },1000)
})
promise.then(res=>{console.log(res)})

实例方法

Promise.prototype.then()

Promise 实例的 then()  方法最多接受两个参数:用于 Promise 兑现和拒绝情况的回调函数。它立即返回一个等效的 Promise 对象,允许你链接到其他 Promise 方法,从而实现链式调用

then(onFulfilled)
then(onFulfilled, onRejected)

示例

const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('this is data')
        // reject('this is reject data')
      }, 1000)
    })
    const onFulfilled = (res) => {
      console.log('onFulfilled res', res)
    }
    const onRejected = (res) => {
      console.log('onRejected res', res)
    }
    promise
      .then(onFulfilled, onRejected)
      .catch((err) => {
        console.error('catch err', err)
      })
      .finally((res) => {
        console.log('finally res', res)
      })

Promise.prototype.catch()

catch(onRejected)

Promise.prototype.finally()

finally(onFinally)

这三个方法都返回一个新的promise

静态方法(常用)

Promise.all()

所有传入的 Promise 都被兑现时兑现;在任意一个 Promise 被拒绝时拒绝。

Promise.all()  静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// Expected output: Array [3, 42, "foo"]

Promise.race()

任意一个 Promise 被敲定时敲定。换句话说,在任意一个 Promise 被兑现时兑现;在任意一个的 Promise 被拒绝时拒绝。

Promise.race()  静态方法接受一个 promise 可迭代对象作为输入,并返回一个 Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。

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);
  // Both resolve, but promise2 is faster
});
// Expected output: "two"

Promise.any()

任意一个 Promise 被兑现时兑现;仅在所有的 Promise 都被拒绝时才会拒绝

Promise.any()  静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。

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));

// Expected output: "quick"

Promise.allSettled()

所有的 Promise 都被敲定时兑现。

Promise.allSettled()  静态方法将一个 Promise 可迭代对象作为输入,并返回一个单独的 Promise。当所有输入的 Promise 都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise 结果的对象数组。

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) =>
  setTimeout(reject, 100, 'foo'),
);
const promises = [promise1, promise2];

Promise.allSettled(promises).then((results) =>
  results.forEach((result) => console.log(result.status)),
);

// Expected output:
// "fulfilled"
// "rejected"

时序

Promise 回调被处理为微任务,而 setTimeout() 回调被处理为任务队列。

任务队列和微任务队列的区别很简单,但却很重要:

当执行来自任务队列中的任务时,在每一次新的事件循环开始迭代的时候运行时都会执行队列中的每个任务。在每次迭代开始之后加入到队列中的任务需要在下一次迭代开始之后才会被执行

每次当一个任务退出且执行上下文栈为空的时候,微任务队列中的每一个微任务会依次被执行。不同的是它会等到微任务队列为空才会停止执行——即使中途有微任务加入。换句话说,微任务可以添加新的微任务到队列中,这些新的微任务将在下一个任务开始运行之前,在当前事件循环迭代结束之前执行。

参考文档

MDN - Promise

MDN - 使用 Promise

MDN - 深入:微任务与 Javascript 运行时环境