一篇文章让你搞懂JS中new Promise的resolve和reject执行顺序
作者:正义的大古
一、在Promise里,如果resolve和reject同时存在,且没有条件约束(同步调用),或者有条件约束(异步/条件判断),它们的执行顺序是怎样的?
1.resolve和reject同级,且没有条件约束(同步调用)
示例代码:
new Promise((resolve, reject) => {
resolve("成功"); // (A)
reject("失败"); // (B)
}).then(
(res) => console.log("then:", res),
(err) => console.log("catch:", err)
);执行顺序:
resolve("成功")(A) 先执行,Promise状态变为 fulfilled。reject("失败")(B) 也会执行,但由于Promise状态已经变成 fulfilled,它会被 忽略。最终进入
.then()的成功回调,输出"then: 成功"。
结论:
✅ resolve 先执行,reject 被忽略(因为 Promise 状态一旦改变就不能再变)。
2.resolve和reject有条件约束(异步/条件判断)
(1) 异步任务(如setTimeout)决定执行顺序
示例代码:
new Promise((resolve, reject) => {
setTimeout(() => resolve("成功"), 1000); // (A) 1秒后执行
setTimeout(() => reject("失败"), 500); // (B) 0.5秒后执行
}).then(
(res) => console.log("then:", res),
(err) => console.log("catch:", err)
);执行顺序:
reject("失败")(B) 先执行(500ms < 1000ms),Promise状态变为 rejected。resolve("成功")(A) 1秒后执行,但Promise已经是 rejected,所以它被 忽略。最终进入
.then()的失败回调,输出"catch: 失败"。
结论:
✅ 先执行的(reject)生效,后执行的(resolve)被忽略。
(2) 条件判断(如if-else)决定执行顺序
示例代码:
let condition = true;
new Promise((resolve, reject) => {
if (condition) {
resolve("成功"); // (A) 执行
} else {
reject("失败"); // (B) 不执行
}
}).then(
(res) => console.log("then:", res),
(err) => console.log("catch:", err)
);执行顺序:
condition为true,所以resolve("成功")(A) 执行,Promise状态变为 fulfilled。reject("失败")(B) 不会执行。最终进入
.then()的成功回调,输出"then: 成功"。
结论:
✅ 条件决定哪个先执行,另一个不会执行。
总结
| 情况 | 执行顺序 | 结果 |
|---|---|---|
| resolve 和 reject 同步调用(无约束) | resolve 先执行,reject 被忽略 | 走 then 成功回调 |
| resolve 和 reject 异步调用(如 setTimeout) | 先调用的生效,后调用的被忽略 | 取决于谁先执行 |
| resolve 和 reject 有条件约束(如 if-else) | 满足条件的执行,另一个不执行 | 由条件决定 |
核心规则
Promise 的状态一旦改变(fulfilled/rejected),就不能再变。
同步代码中,resolve 和 reject 谁在前谁生效。
异步代码中,取决于哪个回调先执行。
条件约束下,满足条件的执行,另一个不执行。
二、在Promise链式调用(.then())的情况下,后续是否还会执行resolve或reject取决于前一个Promise的状态以及.then()回调的返回值。
1..then()的基本行为
.then() 会返回一个新的 Promise,它的状态由它的回调函数决定:
如果回调 正常返回一个值(或没有
return),新的Promise会 resolve 这个值。如果回调 抛出错误(
throw)或返回一个rejected Promise,新的Promise会reject。
示例 1:.then()返回普通值
new Promise((resolve) => resolve("A"))
.then((res) => {
console.log(res); // "A"
return "B"; // ✅ 相当于 resolve("B")
})
.then((res) => {
console.log(res); // "B"
});执行流程:
第一个
Promiseresolve("A")。第一个
.then()接收"A",并返回"B"(相当于resolve("B"))。第二个
.then()接收"B"。
示例 2:.then()抛出错误
new Promise((resolve) => resolve("A"))
.then((res) => {
console.log(res); // "A"
throw new Error("Oops!"); // ❌ 相当于 reject(Error("Oops!"))
})
.then(
(res) => console.log("成功", res), // 不会执行
(err) => console.log("失败", err) // 捕获错误:"失败 Error: Oops!"
);执行流程:
第一个
Promiseresolve("A")。第一个
.then()抛出错误,导致新的Promisereject。第二个
.then()的失败回调捕获错误。
2. 后续是否还能执行resolve或reject?
情况 1:.then()返回新的Promise
如果 .then() 返回一个新的 Promise,那么它的 resolve/reject 会影响后续的链式调用。
示例:
new Promise((resolve) => resolve("A"))
.then((res) => {
console.log(res); // "A"
return new Promise((resolve, reject) => {
setTimeout(() => resolve("B"), 1000); // 1秒后 resolve("B")
});
})
.then((res) => {
console.log(res); // "B"(1秒后打印)
});执行流程:
第一个
Promiseresolve("A")。第一个
.then()返回一个新的Promise,1秒后resolve("B")。第二个
.then()等待这个Promise完成,最终接收"B"。
情况 2:.then()内部再次调用resolve/reject
如果 .then() 内部手动创建 Promise 并调用 resolve/reject,会影响后续流程。
示例:
new Promise((resolve) => resolve("A"))
.then((res) => {
console.log(res); // "A"
return new Promise((resolve, reject) => {
resolve("B"); // ✅ 手动 resolve
reject("Error"); // ❌ 会被忽略(Promise 状态已改变)
});
})
.then(
(res) => console.log("成功", res), // "成功 B"
(err) => console.log("失败", err)
);执行流程:
第一个
Promiseresolve("A")。第一个
.then()返回一个新的Promise,并立即resolve("B"),reject("Error")被忽略。第二个
.then()接收"B"。
3. 关键结论
.then() 会返回一个新的 Promise,它的状态由回调决定:
如果回调返回普通值 → 新
Promiseresolve该值。如果回调抛出错误 → 新
Promisereject该错误。如果回调返回
Promise→ 新Promise跟随它的状态。
后续的 resolve/reject 由 .then() 的回调决定,而不是最初的那个
Promise。Promise 状态一旦改变就不能再变,所以如果
resolve和reject同时出现,先执行的生效,后执行的被忽略。
4.总结
| 情况 | 是否还能执行 resolve/reject? | 说明 |
|---|---|---|
.then() 返回普通值 | ✅ 相当于 resolve(返回值) | 后续 .then() 会接收该值 |
.then() 抛出错误 | ✅ 相当于 reject(错误) | 后续 .catch() 会捕获 |
.then() 返回 Promise | ✅ 跟随该 Promise 的 resolve/reject | 后续 .then() 或 .catch() 取决于它 |
Promise 已经 resolve/reject | ❌ 无法再改变状态 | 后续调用 resolve/reject 无效 |
核心规则:
Promise 链式调用的每一步都是一个新的 Promise。
后续的 resolve/reject 由 .then() 或 .catch() 的回调决定。
一旦 Promise 状态改变,就不能再变,所以
resolve和reject不会冲突。
三、即使Promise被reject,仍然可以继续调用.then()或.catch(),但执行逻辑有所不同。关键在于Promise的链式调用如何处理rejected状态。
1.reject后如何继续调用?
(1) 使用.catch()捕获错误
.catch() 专门用于处理 rejected 状态的 Promise,类似于 try/catch。
示例:
new Promise((resolve, reject) => {
reject("失败"); // ❌ Promise 被 reject
})
.then((res) => {
console.log("成功:", res); // 不会执行
})
.catch((err) => {
console.log("捕获错误:", err); // 输出:"捕获错误: 失败"
return "错误已处理"; // ✅ 返回一个新值,相当于 resolve("错误已处理")
})
.then((res) => {
console.log("后续处理:", res); // 输出:"后续处理: 错误已处理"
});执行流程:
Promise被reject("失败")。第一个
.then()被跳过(因为Promise是rejected状态)。.catch()捕获错误,并返回一个新值(相当于resolve("错误已处理"))。后续的
.then()接收到"错误已处理"。
(2) 使用.then()的第二个参数(错误回调)
.then() 可以接受两个参数:
第一个参数:
onFulfilled(成功回调)。第二个参数:
onRejected(失败回调)。
示例:
new Promise((resolve, reject) => {
reject("失败"); // ❌ Promise 被 reject
})
.then(
(res) => console.log("成功:", res), // 不会执行
(err) => {
console.log("失败回调:", err); // 输出:"失败回调: 失败"
return "从错误中恢复"; // ✅ 返回一个新值,相当于 resolve("从错误中恢复")
}
)
.then((res) => {
console.log("后续处理:", res); // 输出:"后续处理: 从错误中恢复"
});执行流程:
Promise被reject("失败")。.then()的第二个参数(错误回调)被执行,并返回 "从错误中恢复"。后续的
.then()接收到 "从错误中恢复"。
2. 关键区别:.catch()vs.then()的第二个参数
| 方式 | 特点 | 适用场景 |
|---|---|---|
| .catch() | 专用于错误处理,代码更清晰 | 链式调用中统一处理错误 |
| .then() 的第二个参数 | 直接绑定到当前 .then() | 需要针对特定步骤处理错误 |
推荐使用 .catch(),因为它更符合链式调用的习惯,且能捕获前面所有 .then() 中的错误。
3. 如果既不.catch()也不传错误回调?
如果 reject 后没有错误处理,控制台会报 Uncaught (in promise) 警告,但后续 .then() 仍会执行(只是接收不到 reject 的值)。
示例:
new Promise((resolve, reject) => {
reject("失败"); // ❌ 未捕获的错误
})
.then((res) => {
console.log("成功:", res); // 不会执行
})
.then((res) => {
console.log("仍然执行,但 res=", res); // 输出:"仍然执行,但 res= undefined"
});执行结果:
控制台警告:
Uncaught (in promise) 失败。最后一个
.then()仍然执行,但res是undefined(因为没有前一步的返回值)。
4. 总结
| 问题 | 答案 |
|---|---|
| reject 后还能继续调用 .then() 吗? | ✅ 可以,但需要通过 .catch() 或 .then() 的第二个参数处理错误。 |
| reject 后不处理会怎样? | ❌ 控制台报 Uncaught (in promise) 警告,但后续 .then() 仍会执行(res=undefined)。 |
| 如何优雅地处理 reject? | 使用 .catch() 或 .then() 的第二个参数,并返回新值以继续链式调用。 |
最终建议:
在链式调用中,始终用 .catch() 处理错误,避免未捕获的 Promise 错误!
到此这篇关于JS中new Promise的resolve和reject执行顺序的文章就介绍到这了,更多相关JS resolve和reject执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
