【问题标题】:Synchronous Promise Chaining [duplicate]同步承诺链[重复]
【发布时间】:2021-09-25 02:30:45
【问题描述】:

我正在尝试理解 Promise 链接,我的印象是以下代码应该同步运行,因为我链接了“then”语句。为什么第 2 次和第 3 次数据获取异步运行。

console.log("Start Program")
console.log("Start Getting Data 1")

new Promise((succes) => {
    setTimeout(()=>{
        console.log("Got Data 1")
        succes()},3000)
    }
).then(()=>{
    console.log("Start Getting Data 2")
    setTimeout(()=>{console.log("Got Data 2")},3000)
}).then(()=>{
    console.log("Start Getting Data 3")
    setTimeout(()=>{console.log("Got Data 3")},3000)
})

console.log("End Program")

【问题讨论】:

  • 你必须为你的第一个.then中的每个.then返回一个新的承诺,再返回一个承诺
  • 你的第二次超时只是在一定时间后记录一些东西,它不会解决任何承诺,对承诺链没有影响。
  • 如果你实际获取数据,问题会更少,只需返回结果(正常功能应该如此)

标签: javascript asynchronous promise chain


【解决方案1】:

这是因为您没有从第二个返回 Promise。所以,基本上,先完成后,接下来的2个函数都会被触发。

如果你想让 3 等 2 必须做:

console.log("Start Program")
console.log("Start Getting Data 1")

new Promise((succes) => {
    setTimeout(()=>{
        console.log("Got Data 1")
        succes()},3000)
    }
).then(()=>{   
     console.log("Start Getting Data 2")
 return new Promise((succes) => {
    setTimeout(()=>{
        console.log("Got Data 2")
        succes()},3000)
    }
)
}).then(()=>{
    console.log("Start Getting Data 3")
    setTimeout(()=>{console.log("Got Data 3")},3000)
})

【讨论】:

    【解决方案2】:

    要解决您的问题,您需要从 then() 处理程序返回一个新的承诺。否则下一个then() 处理程序将在前一个处理程序之后立即执行。

    ).then(()=>{
        console.log("Start Getting Data 2")
        setTimeout(()=>{console.log("Got Data 2")},3000)
        // no promise is returned, next then handler will execute
        // immediately
    }).then(()=>{
    

    为了简化与 setTimeout MDN 结合的 Promise 创建,建议将其包装在尽可能低的级别。创建一个辅助函数,除了将旧的回调函数包装在一个 Promise 中之外什么都不做。

    Creating a Promise around an old callback API

    Promise 可以使用其构造函数从头开始创建。 这应该只需要包装旧的 API。

    在理想情况下,所有异步函数都已经返回 承诺。不幸的是,一些 API 仍然期望成功和/或失败 以旧方式传递的回调。最明显的例子是 setTimeout()函数:

    setTimeout(() => saySomething("10 seconds passed"), 10*1000);
    

    混合旧式回调和承诺是有问题的。如果 saySomething() 失败或包含编程错误,没有 抓住它。 setTimeout 应该为此负责。

    幸运的是,我们可以将setTimeout 包装在一个承诺中。 最佳做法是 将有问题的函数包装在尽可能低的级别,然后 永远不要再直接打电话给他们:

    const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    wait(10*1000).then(() => saySomething("10 seconds")).catch(failureCallback);
    

    基本上,promise 构造函数接受一个执行函数 让我们手动解决或拒绝一个承诺。由于setTimeout() 并没有真正失败,在这种情况下我们忽略了拒绝。

    const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    console.log("Start Program")
    console.log("Start Getting Data 1")
    
    wait(3000)
    .then(() => {
      console.log("Got Data 1");
      // By not returning the next `then()` handler will be
      // executed immediately.
    })
    .then(() => {
      console.log("Start Getting Data 2");
      // Return a new promise so the next `then()` handler is
      // not immediately executed.
      return wait(3000);
    })
    .then(() => {
      console.log("Got Data 2");
    })
    .then(() => {
      console.log("Start Getting Data 3");
      return wait(3000); // <- return promise so next `then` waits
    })
    .then(() => {
      console.log("Got Data 3");
    });

    上面的内容可以通过结合"Got Data""Start Getting Data" 控制台日志来浓缩。

    const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    console.log("Start Program")
    console.log("Start Getting Data 1")
    
    wait(3000)
    .then(() => {
      console.log("Got Data 1");
      console.log("Start Getting Data 2");
      return wait(3000);
    })
    .then(() => {
      console.log("Got Data 2");
      console.log("Start Getting Data 3");
      return wait(3000);
    })
    .then(() => {
      console.log("Got Data 3");
    });

    【讨论】:

      猜你喜欢
      • 2016-01-05
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-02
      • 1970-01-01
      • 2019-07-29
      • 1970-01-01
      相关资源
      最近更新 更多