JavaScript中Promise的then()函数

原文:The Promise then() Function in JavaScript

then()函数是JavaScript中Promise交互的主要方式,是Promise链式语法的一部分。

JavaScript的Promise代表了一个异步操作。可以认为Promise是一个还未被计算的值的占位符。然而,没办法直接从Promise获取到这个值——需要调用then()函数注册一个回调函数,当值被计算完成后JavaScript会调用这个回调函数。

1
2
3
4
5
6
// 创建一个Promise,立刻变为`fulfilled`,返回数值42。
const promise = Promise.resolve(42);

promise.then(value => {
value; // 42
});

then()函数的参数

then()函数接收2个回调函数作为参数:

  • onFulfilled():底层的异步操作成功后调用。
  • onRejected():底层的异步操作失败后调用。

回忆一下,Promise是3个状态的状态机

  • Pending:操作正在进行中。
  • Fulfilled:操作成功完成。
  • Rejected:操作发生错误。

Promise总是以pending状态作为起始。如果Promise变成fulfilled状态,JavaScript调用onFulfilled()函数。如果在Promise已经是fulfilled状态,再调用then(),JavaScript会立即调用onFulfilled()

1
2
3
4
5
6
7
8
const promise = new Promise(function executor(resolve, reject) {
// 100毫秒后Promise变为fulfilled,并返回值42
setTimeout(() => resolve(42), 100);
});

promise.then(value => {
value; // 42
});

如果Promise变成rejected状态,或者Promise已经是rejected状态时调用then(),JavaScript会调用onFulfilled()

1
2
3
4
5
6
// 创建一个 Promise 立刻变为 `rejected` 并返回一个错误对象
const promise = Promise.reject(new Error('Oops!'));

promise.then(null, err => {
err.message; // 'Oops!'
});

onFulfilled()onRejected()都是可选参数。如果像以上示例一样onFulfilled()是null,JavaScript在Promise变为fulfilled时不会做任何事。如果Promise状态是rejected,调用.then()时不带onRejected()函数,会导致未捕获的错误

then()和catch()

Promise#catch()函数.then()一个方便的简写,.catch(onRejected)相当于.then(null, onRejected)的语法糖。

1
2
3
4
5
6
7
// 创建一个 Promise 立刻变为 `rejected` 并返回一个错误对象
const promise = Promise.reject(new Error('Oops!'));

// 等价于 `.then(null, onRejected)`
promise.catch(function onRejected() {
err.message; // 'Oops!'
});

虽然.catch()在原理上不复杂,但catch这个名字很有用,因为可以把Promise.catch()类比try/catch中的catch,当你在浏览包含Promise的代码时,.catch()可以很容易分辨错误处理代码。

链式操作

说到Promise的实用性,Promise的链式操作功不可没。then()函数返回一个Promise p,如果传入的onFulfilled()函数返回一个Promise qp会沿用q的状态。

1
2
3
4
5
6
7
// 创建一个 Promise 立刻变为 `rejected` 并返回一个错误对象
const promise = Promise.reject(new Error('Oops!'));

// 等价于 `.then(null, onRejected)`
promise.catch(function onRejected() {
err.message; // 'Oops!'
});

由于Promise的链式特性,不需要在每个then()中用捕获错误。在Promise链的结尾加一个catch(),链中的任何错误,都会穿过Promise链,直到被catch()捕获错误。

1
2
3
4
5
6
7
Promise.resolve(1).
then(() => Promise.resolve(2)).
then(() => Promise.reject(new Error('Oops!'))).
then(() => console.log('This will not print')).
catch(function errorHandler(err) {
err.message; // 'Oops!'
});

async/await是JavaScript中并发的未来趋势。“Mastering Async/Await”教你如何在几个小时内,用async/await构建前后端APP,来看看吧!