【问题标题】:Promise chain .then .catch承诺链 .then .catch
【发布时间】:2021-10-17 10:03:00
【问题描述】:

这个承诺链是如何工作的?

Promise.resolve(1)
  .then(x => console.log(1))
  .catch(x => console.log(2))
  .then(x => console.log(3))

Promise.reject(1)
  .then(x => console.log(4))
  //.then(x => console.log(5))
  .catch(x => console.log(6))
  .then(x => console.log(7))

结果 1 6 3 7

为什么结果不等于 1 3 6 7 ?

如果添加.then(x => console.log(5)),则结果等于 1 3 6 7。 它是如何工作的?

【问题讨论】:

  • 如果承诺链未链接,您应该期望任何特定的承诺解决顺序。您拥有的唯一保证是同一承诺链的链接按相互关联的顺序解析。就是这样。
  • @T.J.Crowder 你的意思是this search?你的有user:me。我很困惑为什么你认为我的答案是相关的:P
  • 但是,虽然这两个链之间的顺序是定义的,只要代码完全如图所示,它不是你应该依赖的东西。如果您需要在两个 Promise 链之间进行协调,请有意地协调它们。 :-)
  • @T.J.Crowder 只是补充一下 - 这是here的解释,因为它们以循环顺序解决。但不一定适用于任何两个承诺链。在某些情况下,解决单个承诺需要不止一个滴答声,因此订单可能不是a b a b a b,而是a b b b a a。因此建议不要依赖任何具体的东西。
  • @VLAZ 将“在某些情况下”设为“在大多数情况下”。如果你总是立即解决它们,你根本不应该使用它们:-)

标签: javascript promise


【解决方案1】:

正如其他人在问题下的 cmets 中提到的那样,您不应依赖解决不相关承诺的时间或顺序。

话虽如此,您的代码产生的输出有一个解释。

传递给then()catch() 方法的回调被异步调用并排入微任务队列。

  1. 调用Promise.resolve(1) 创建一个已解决的承诺;因此,传递给Promise.resolve(1).then(...) 的回调被放入微任务队列中。

    [
      (x) => console.log(1)
    ]
    
  2. 在此之后,Promise.reject(1) 被调用,这会创建一个被拒绝的承诺。这将拒绝Promise.reject(1).then(...) 返回的承诺。

    [
      reject(Promise.reject(1).then(...)),
      (x) => console.log(1)
    ]
    
  3. 脚本执行结束

  4. 事件循环将开始处理其中有两个任务的微任务队列

    [
      reject(Promise.reject(1).then(...)),
      (x) => console.log(1)
    ]
    
  5. 1 已登录控制台。登录 1 后,Promise.resolve(1).then(...) 返回的 promise 将通过 undefined 的值实现。

    这将导致Promise.resolve(1).then(...).catch(...)返回的承诺的履行

    [
      resolve(Promise.resolve(1).then(...).catch(...))
      reject(Promise.reject(1).then(...))
    ]
    
  6. 队列中的下一个任务是拒绝Promise.reject(1).then(...) 返回的承诺。拒绝承诺让另一个微任务排队

    queue: [
             x => console.log(6),
             resolve(Promise.resolve(1).then(...).catch(...))
           ]
    
    console output: 1
    
  7. Promise.resolve(1).then(...).catch(...) 返回的 Promise 被解析到微任务队列中的哪些队列 @9​​87654339@

    queue: [
             x => console.log(3),
             x => console.log(6)
           ]
    
    console output: 1
    
  8. “6”登录到控制台

    queue: [
             x => console.log(3),
           ]
    
    console output: 1 6
    
  9. 在记录6 后,catch 方法返回的承诺如果满足 undefined 的值,该值将另一个微任务排队

    queue: [
             x => console.log(7),
             x => console.log(3)
           ]
    
    console output: 1 6
    
  10. 3 登录控制台

    queue: [
             x => console.log(7),
           ]
    
    console output: 1 6 3
    
  11. 7 登录控制台

    queue: []
    
    console output: 1 6 3 7
    

如果添加 .then(x => console.log(5)),则结果等于 1 3 6 7。

通过额外的then()方法调用,在微任务处理周期中多走一步排队

x => console.log(6)

在微任务队列中导致

x => console.log(3)

得到处理之前 x => console.log(6).

【讨论】:

    猜你喜欢
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    • 2015-08-15
    相关资源
    最近更新 更多