一篇文章让你搞懂JS中new Promise的resolve和reject执行顺序

 更新时间:2025年11月15日 15:59:00   作者:正义的大古  
在JavaScript中new Promise是用来创建一个Promise对象的构造函数,它接受一个执行器函数作为参数,这篇文章主要介绍了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)
);

执行顺序:

  1. resolve("成功") (A) 先执行,Promise 状态变为 fulfilled

  2. reject("失败") (B) 也会执行,但由于 Promise 状态已经变成 fulfilled,它会被 忽略

  3. 最终进入 .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)
);

执行顺序:

  1. reject("失败") (B) 先执行(500ms < 1000ms),Promise 状态变为 rejected

  2. resolve("成功") (A) 1秒后执行,但 Promise 已经是 rejected,所以它被 忽略

  3. 最终进入 .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)
);

执行顺序:

  1. condition 为 true,所以 resolve("成功") (A) 执行,Promise 状态变为 fulfilled

  2. reject("失败") (B) 不会执行。

  3. 最终进入 .then() 的成功回调,输出 "then: 成功"

结论:

✅ 条件决定哪个先执行,另一个不会执行

总结

情况执行顺序结果
resolve 和 reject 同步调用(无约束)resolve 先执行,reject 被忽略走 then 成功回调
resolve 和 reject 异步调用(如 setTimeout)先调用的生效,后调用的被忽略取决于谁先执行
resolve 和 reject 有条件约束(如 if-else)满足条件的执行,另一个不执行由条件决定

核心规则

  1. Promise 的状态一旦改变(fulfilled/rejected),就不能再变

  2. 同步代码中,resolve 和 reject 谁在前谁生效

  3. 异步代码中,取决于哪个回调先执行

  4. 条件约束下,满足条件的执行,另一个不执行

二、在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"
  });

执行流程:

  1. 第一个 Promise resolve("A")

  2. 第一个 .then() 接收 "A",并返回 "B"(相当于 resolve("B"))。

  3. 第二个 .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!"
  );

执行流程:

  1. 第一个 Promise resolve("A")

  2. 第一个 .then() 抛出错误,导致新的 Promise reject

  3. 第二个 .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秒后打印)
  });

执行流程:

  1. 第一个 Promise resolve("A")

  2. 第一个 .then() 返回一个新的 Promise,1秒后 resolve("B")

  3. 第二个 .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)
  );

执行流程:

  1. 第一个 Promise resolve("A")

  2. 第一个 .then() 返回一个新的 Promise,并立即 resolve("B")reject("Error") 被忽略。

  3. 第二个 .then() 接收 "B"

3. 关键结论

  1. .then() 会返回一个新的 Promise,它的状态由回调决定:

    • 如果回调返回普通值 → 新 Promise resolve 该值。

    • 如果回调抛出错误 → 新 Promise reject 该错误。

    • 如果回调返回 Promise → 新 Promise 跟随它的状态。

  2. 后续的 resolve/reject 由 .then() 的回调决定,而不是最初的那个 Promise

  3. Promise 状态一旦改变就不能再变,所以如果 resolve 和 reject 同时出现,先执行的生效,后执行的被忽略。

4.总结

情况是否还能执行 resolve/reject?说明
.then() 返回普通值✅ 相当于 resolve(返回值)后续 .then() 会接收该值
.then() 抛出错误✅ 相当于 reject(错误)后续 .catch() 会捕获
.then() 返回 Promise✅ 跟随该 Promise 的 resolve/reject后续 .then() 或 .catch() 取决于它
Promise 已经 resolve/reject❌ 无法再改变状态后续调用 resolve/reject 无效

核心规则:

  1. Promise 链式调用的每一步都是一个新的 Promise

  2. 后续的 resolve/reject 由 .then() 或 .catch() 的回调决定

  3. 一旦 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); // 输出:"后续处理: 错误已处理"
});

执行流程:

  1. Promise 被 reject("失败")

  2. 第一个 .then() 被跳过(因为 Promise 是 rejected 状态)。

  3. .catch() 捕获错误,并返回一个新值(相当于 resolve("错误已处理"))。

  4. 后续的 .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); // 输出:"后续处理: 从错误中恢复"
});

执行流程:

  1. Promise 被 reject("失败")

  2. .then() 的第二个参数(错误回调)被执行,并返回 "从错误中恢复"。

  3. 后续的 .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"
});

执行结果:

  1. 控制台警告:Uncaught (in promise) 失败

  2. 最后一个 .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执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript DOM API的使用教程及综合案例

    JavaScript DOM API的使用教程及综合案例

    dom是Document Object Model的缩写,即文档对象模型,是基于文档编程的一套API接口,下面这篇文章主要给大家介绍了关于JavaScript DOM API的使用教程及综合案例的相关资料,需要的朋友可以参考下
    2023-03-03
  • jfinal与bootstrap的登出实战详解

    jfinal与bootstrap的登出实战详解

    这篇文章主要为大家详细介绍了jfinal与bootstrap的登出实战,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • js 获取站点应用名的简单实例

    js 获取站点应用名的简单实例

    下面小编就为大家带来一篇js 获取站点应用名的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • JavaScript 正则命名分组【推荐】

    JavaScript 正则命名分组【推荐】

    以往我们只是习惯于通过数组下标来访问正则匹配到的分组,但分组达到4、5个时,标识起来就会非常麻烦。V8早已实现了正则命名分组提案,只是我们很少使用,本文将介绍JS的正则命名分组
    2018-06-06
  • JavaScript简单下拉菜单实例代码

    JavaScript简单下拉菜单实例代码

    这篇文章主要介绍了JavaScript简单下拉菜单,采用JavaScript定时函数递归调用实现菜单渐显效果,非常简单实用,需要的朋友可以参考下
    2015-09-09
  • Javascript 原型与原型链深入详解

    Javascript 原型与原型链深入详解

    这篇文章主要介绍了Javascript原型与原型链深入详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-07-07
  • 详解JS中的柯里化(currying)

    详解JS中的柯里化(currying)

    这篇文章主要介绍了JS中的柯里化(currying),需要的朋友可以参考下
    2017-08-08
  • 微信小程序获取用户openid的实现

    微信小程序获取用户openid的实现

    这篇文章主要介绍了微信小程序获取用户openid的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • Bootstrap模态对话框中显示动态内容的方法

    Bootstrap模态对话框中显示动态内容的方法

    今天小编就为大家分享一篇Bootstrap模态对话框中显示动态内容的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • 超详细的javascript数组方法汇总

    超详细的javascript数组方法汇总

    这篇文章主要对javascript的数组方法进行了详细的汇总,包括了最常用的的数组方法,还有扩展方法,很全面,感兴趣的小伙伴们可以参考一下
    2015-11-11

最新评论