Promise.prototype.then()
Promise 实例的 then() 方法最多接受两个参数:用于 Promise 的 fulfilled(已fulfilled)和 rejected(已rejected)情况的回调函数。它将这些回调函数存储在调用它的 Promise 对象中,并立即返回另一个 Promise 对象,允许你 链式调用 其他 Promise 方法。
试一试
const promise1 = new Promise((resolve, reject) => {
resolve("Success!");
});
promise1.then((value) => {
console.log(value);
// Expected output: "Success!"
});
语法
then(onFulfilled)
then(onFulfilled, onRejected)
参数
onFulfilled-
当此 Promise 变为 fulfilled 时异步执行的函数。其返回值将成为
then()返回的 Promise 的 fulfillment 值。该函数以以下参数被调用:value-
Promise fulfilled 时的值。
如果它不是一个函数,它会被内部替换为一个恒等函数(
(x) => x),该函数仅将 fulfillment 值向前传递。 onRejected可选-
当此 Promise 变为 rejected 时异步执行的函数。其返回值将成为
then()返回的 Promise 的 fulfillment 值。该函数以以下参数被调用:reason-
Promise rejected 时的值。
如果它不是一个函数,它会被内部替换为一个抛出函数(
(x) => { throw x; }),该函数会抛出它接收到的 rejection reason。
返回值
立即返回一个新的 Promise。这个返回的 Promise 在返回时始终处于 pending(等待)状态,无论当前 Promise 的状态如何。
onFulfilled 和 onRejected 这两个处理程序中的一个将被执行,以处理当前 Promise 的 fulfillment 或 rejection。即使当前 Promise 已经 settled(已定型),调用也总是异步发生的。then() 返回的 Promise(在以下列表中称为 p)的行为取决于处理程序的执行结果,遵循一套特定的规则。如果处理函数
- 返回一个值:
p将以返回的值作为其值而被 fulfilled。 - 不返回任何东西:
p将以undefined作为其值而被 fulfilled。 - 抛出一个错误:
p将以抛出的错误作为其值而被 rejected。 - 返回一个已 fulfilled 的 Promise:
p将以该 Promise 的值作为其值而被 fulfilled。 - 返回一个已 rejected 的 Promise:
p将以该 Promise 的值作为其值而被 rejected。 - 返回另一个 pending 的 Promise:
p将保持 pending 状态,并在该 Promise 变为 fulfilled/rejected 后,立即以该 Promise 的值作为其值而被 fulfilled/rejected。
描述
then() 方法为 Promise 的最终完成(fulfilled 或 rejected)安排回调函数。它是 Promise 的基本方法:thenable 协议要求所有类 Promise 对象都公开一个 then() 方法,而 catch() 和 finally() 方法都通过调用对象的 then() 方法来工作。
有关 onRejected 处理程序的更多信息,请参阅 catch() 参考。
then() 返回一个新的 Promise 对象,但会修改调用它的 Promise 对象,将处理程序附加到内部列表中。因此,处理程序会被原始 Promise 保留,其生命周期至少与原始 Promise 的生命周期一样长。例如,下面的示例即使返回的 Promise 未被保留,最终也会耗尽内存。
const pendingPromise = new Promise(() => {});
while (true) {
pendingPromise.then(doSomething);
}
如果您对同一个 Promise 对象调用两次 then() 方法(而不是链式调用),那么这个 Promise 对象将有两对 settlement 处理程序。附加到同一 Promise 对象的每个处理程序始终按照它们被添加的顺序调用。此外,每次调用 then() 返回的两个 Promise 会启动独立的链,并且不会等待彼此的 settlement。
在 then() 链中出现的 Thenable 对象总是会被 resolved — onFulfilled 处理程序永远不会接收到一个 thenable 对象,并且任何由这两个处理程序之一返回的 thenable 在传递给下一个处理程序之前都会被 resolved。这是因为在构造新的 Promise 时,executor 传递的 resolve 和 reject 函数会被保存,当当前 Promise settle 时,相应的函数将被用 fulfillment 值或 rejection reason 调用。resolving 逻辑来自 Promise() 构造函数传递的 resolve 函数。
then() 支持子类继承,这意味着它可以被 Promise 的子类实例调用,结果将是该子类类型的 Promise。你可以通过 [Symbol.species] 属性来自定义返回值的类型。
示例
使用 then() 方法
const p1 = new Promise((resolve, reject) => {
resolve("Success!");
// or
// reject(new Error("Error!"));
});
p1.then(
(value) => {
console.log(value); // Success!
},
(reason) => {
console.error(reason); // Error!
},
);
将非函数作为参数
Promise.resolve(1).then(2).then(console.log); // 1
Promise.reject(new Error("failed")).then(2, 2).then(console.log, console.log); // Error: failed
链式调用
then 方法返回一个新的 Promise,这允许进行方法链式调用。
如果传递给 then 作为处理程序的函数返回一个 Promise,那么链式调用中的后续 then 将会获得一个等效的 Promise。下面的代码片段使用 setTimeout 函数模拟了异步代码。
Promise.resolve("foo")
// 1. Receive "foo", concatenate "bar" to it, and resolve that to the next then
.then(
(string) =>
new Promise((resolve, reject) => {
setTimeout(() => {
string += "bar";
resolve(string);
}, 1);
}),
)
// 2. receive "foobar", register a callback function to work on that string
// and print it to the console, but not before returning the unworked on
// string to the next then
.then((string) => {
setTimeout(() => {
string += "baz";
console.log(string); // foobarbaz
}, 1);
return string;
})
// 3. print helpful messages about how the code in this section will be run
// before the string is actually processed by the mocked asynchronous code in the
// previous then block.
.then((string) => {
console.log(
"Last Then: oops... didn't bother to instantiate and return a promise in the prior then so the sequence may be a bit surprising",
);
// Note that `string` will not have the 'baz' bit of it at this point. This
// is because we mocked that to happen asynchronously with a setTimeout function
console.log(string); // foobar
});
// Logs, in order:
// Last Then: oops... didn't bother to instantiate and return a promise in the prior then so the sequence may be a bit surprising
// foobar
// foobarbaz
then() 返回的值与 Promise.resolve() 的解析方式相同。这意味着 thenable 对象是被支持的,如果返回值不是 Promise,它会被隐式地包装成一个 Promise 然后再解析。
const p2 = new Promise((resolve, reject) => {
resolve(1);
});
p2.then((value) => {
console.log(value); // 1
return value + 1;
}).then((value) => {
console.log(value, "- A synchronous value works"); // 2 - A synchronous value works
});
p2.then((value) => {
console.log(value); // 1
});
如果函数抛出错误或返回一个 rejected Promise,then 调用返回一个最终 rejected 的 Promise。
Promise.resolve()
.then(() => {
// Makes .then() return a rejected promise
throw new Error("Oh no!");
})
.then(
() => {
console.log("Not called.");
},
(error) => {
console.error(`onRejected function called: ${error.message}`);
},
);
在实践中,通常更倾向于使用 catch() 来处理 rejected Promises,而不是 then() 的两部分语法,如下例所示。
Promise.resolve()
.then(() => {
// Makes .then() return a rejected promise
throw new Error("Oh no!");
})
.catch((error) => {
console.error(`onRejected function called: ${error.message}`);
})
.then(() => {
console.log("I am always called even if the prior then's promise rejects");
});
在所有其他情况下,返回的 Promise 最终会 fulfill。在下面的示例中,第一个 then() 返回 42,该值被包装在一个 fulfilled Promise 中,即使链中的前一个 Promise 被 rejected。
Promise.reject(new Error("Oh no!"))
.then(
() => 99,
() => 42,
) // onRejected returns 42 which is wrapped in a fulfilled Promise
.then((solution) => console.log(`Resolved with ${solution}`)); // Fulfilled with 42
如果 onFulfilled 返回一个 Promise,then 的返回值将根据该 Promise 的最终状态而被 fulfilled/rejected。
function resolveLater(resolve, reject) {
setTimeout(() => {
resolve(10);
}, 1000);
}
function rejectLater(resolve, reject) {
setTimeout(() => {
reject(new Error("Error"));
}, 1000);
}
const p1 = Promise.resolve("foo");
// Return promise here, that will be resolved to 10 after 1 second
const p2 = p1.then(() => new Promise(resolveLater));
p2.then(
(v) => {
console.log("resolved", v); // "resolved", 10
},
(e) => {
// not called
console.error("rejected", e);
},
);
// Return promise here, that will be rejected with 'Error' after 1 second
const p3 = p1.then(() => new Promise(rejectLater));
p3.then(
(v) => {
// not called
console.log("resolved", v);
},
(e) => {
console.error("rejected", e); // "rejected", 'Error'
},
);
你可以使用链式调用来实现一个函数,该函数建立在另一个基于 Promise 的 API 之上。
function fetchCurrentData() {
// The fetch() API returns a Promise. This function
// exposes a similar API, except the fulfillment
// value of this function's Promise has had more
// work done on it.
return fetch("current-data.json").then((response) => {
if (response.headers.get("content-type") !== "application/json") {
throw new TypeError();
}
const j = response.json();
// maybe do something with j
// fulfillment value given to user of
// fetchCurrentData().then()
return j;
});
}
then() 的异步性
以下示例演示了 then 方法的异步性。
// Using a resolved promise 'resolvedProm' for example,
// the function call 'resolvedProm.then(...)' returns a new promise immediately,
// but its handler '(value) => {...}' will get called asynchronously as demonstrated by the console.logs.
// the new promise is assigned to 'thenProm',
// and thenProm will be resolved with the value returned by handler
const resolvedProm = Promise.resolve(33);
console.log(resolvedProm);
const thenProm = resolvedProm.then((value) => {
console.log(
`this gets called after the end of the main stack. the value received is: ${value}, the value returned is: ${
value + 1
}`,
);
return value + 1;
});
console.log(thenProm);
// Using setTimeout, we can postpone the execution of a function to the moment the stack is empty
setTimeout(() => {
console.log(thenProm);
});
// Logs, in order:
// Promise {[[PromiseStatus]]: "resolved", [[PromiseResult]]: 33}
// Promise {[[PromiseStatus]]: "pending", [[PromiseResult]]: undefined}
// "this gets called after the end of the main stack. the value received is: 33, the value returned is: 34"
// Promise {[[PromiseStatus]]: "resolved", [[PromiseResult]]: 34}
规范
| 规范 |
|---|
| ECMAScript® 2026 语言规范 # sec-promise.prototype.then |
浏览器兼容性
加载中…