Featured image of post Promise

Promise

Promise 的用途

在 JavaScript 的世界中,所有代码都是单线程执行的。由于这个特性,导致 JavaScript 的所有网络操作,浏览器事件,都必须是异步执行。

而 Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了 Promise。

所谓 Promise ,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

本质上 Promise 是一个函数返回的对象,它代表了一个异步操作的最终完成或者失败。我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了。

创建一个 new Promise

1
return new Promise((resolve,reject)=>{})

一个 Promise 必然处于以下几种状态之一:

  • pending: 待定,初始状态,既没有被兑现,也没有被拒绝。
  • fulfilled: 已兑现,意味着操作成功完成。
  • rejected: 已拒绝,意味着操作失败。
  • resolve 函数的作用是,将 Promise 对象的状态从 “未完成” 变为 “成功” ,即从 pending 变为 resolved ,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

  • reject 函数的作用是,将 Promise 对象的状态从 “未完成” 变为 “失败” ,即从 pending 变为 rejected ,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

如何使用 Promise.prototype.then

待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled),要么会通过一个 原因/错误 被拒绝(rejected)。当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。

then() 方法是为 Promise 实例添加状态改变时的回调函数,它返回一个 Promise 对象。

then方法最多需要有两个参数:Promise 的成功和失败情况的回调函数。第一个参数是 resolved 状态的回调函数,第二个参数(可选)是 rejected 状态的回调函数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let fn = new Promise((resolve, reject) => {
  resolve('成功!')
  // or
  // reject(new Error("出错了!"));
});

p1.then(value => {
  console.log(value); // 成功!
}, reason => {
  console.error(reason); // 出错了!
});

Promise的链式调用

因为 Promise.prototype.then 方法返回的是一个新生成的 promise,这个对象可以被非强制性的用来做链式调用,就像这样:

1
2
3
4
5
const thisPromise =
  (new Promise(fn1))
  .then(fn2)
  .then(fn3)
  .then(fn4);

如何使用 Promise.all

Promise.all() 方法接收一个 promise 的 iterable 类型的输入,并且只返回一个 Promise 实例。

Promise.all() 实际上是一个 promise,它将一组 promise 作为输入(可迭代)。然后,当所有 promise 都执行成功其中任何一个执行失败 时,它就会执行。

  • 该 Promise 的 resolve 回调执行是在所有输入的 promise 的 resolve 回调都结束(即全部执行成功),或者输入的 iterable 里没有 promise 了的时候。
  • 它的reject 回调执行是只要任何一个输入的 promise 的 reject 回调执行(即任何一个执行失败)或者输入不合法的 promise 就会立即抛出错误,并且 reject 的是 第一个 抛出的错误信息。

Promise.all 的使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
let p1 = Promise.resolve(3)
let p2 = 1337
let p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo')
})

Promise.all([p1, p2, p3])
    .then(values => {
        console.log(values)
    })

// [3, 1337, "foo"]

如何使用 Promise.race

Promise.race() 方法接收一个 promise 的 iterable 类型的输入,并且只返回一个 Promise 实例。

只要给定的迭代中的一个 promise 解决或拒绝,就采用第一个执行的 promise 的值作为它的值,从而异步地解析或拒绝(一旦堆栈为空),即 Promise.race() 方法返回的 promise 的状态与传入的 promise 的第一个 promise 执行状态相同。

如果传的迭代是空的,则返回的 promise 将永远等待。

Promise.race 的使用

例中虽然传入的顺序为 p1 > p2,但是 p1 和 p2 的执行顺序为 p2 > p1。

由于 Promise.race() 返回的 promise 的值与第一个执行的 promise 的值相同,所以例中虽然先传入 p1,但 race 的值为 p2。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
let p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 50000, 'p1')
})

let p2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'p2')
})

Promise.race([p1, p2])
    .then((value) => {
        console.log(value)
    })

// p2