【问题标题】:Why does this promise resolve when I am not awaiting it为什么当我不等待这个承诺时它会解决
【发布时间】:2021-12-22 21:13:21
【问题描述】:

我有以下承诺,但如果我在 ts 操场上运行此代码,它似乎无需我等待就可以解决。

const promises = [later(1000)];


function later(delay:number) {
    return new Promise<void>(function(resolve) {
        setTimeout(() => {
          console.log('test');
          resolve();
        }, delay);
    });
}

我只希望它在我调用时执行

await Promise.all(promises);

【问题讨论】:

  • await 不会触发/执行任何操作。 Promisenew Promise(...) 开头。
  • 代码在later(1000)被调用的那一刻被执行,这发生在第一行。
  • 我假设 later 是这里的一个示例 - 但请注意,我们已经在 Node.js 中提供了一个返回承诺的 setTimeout 变体,您可以“直接”使用它。
  • 承诺不是函数。你不能“执行”它。

标签: typescript promise


【解决方案1】:

承诺是价值,而不是行动。一旦你对某事做出承诺相应的行动已经发生

幸运的是,该语言为动作提供了简洁的抽象——函数。您通常使承诺“懒惰”的方式是使用返回承诺的函数而不是承诺本身。

(注意,这与例如可观察对象不同,动作并且订阅它们会调用它们)

【讨论】:

    【解决方案2】:

    正如其他帖子/cmets 所说,later(1000) 会立即被评估,不要等待您的 await Promise.all 调用来运行承诺代码。

    您可以通过以下方式实现:

    const promises = [() => later(1000)];
    
    function later(delay:number) {
        return new Promise<void>(function(resolve) {
            setTimeout(() => {
              console.log('test');
              resolve();
            }, delay);
        });
    }
    
    await Promise.all(promises.map(f => f()));
    

    【讨论】:

      【解决方案3】:

      promises 包装在一个匿名函数中以延迟执行。 TS Playground

      // defer promises
      const promises = () => [later(1000)];
      
      // unmodified
      function later(delay:number) {
          return new Promise<void>(function(resolve) {
              setTimeout(() => {
                console.log('test');
                resolve();
              }, delay);
          });
      }
      
      // call the promises when ready
      (async function () {
          await Promise.all(promises());
      })()
      

      【讨论】:

        【解决方案4】:

        还有thenables;在打字稿PromiseLike&lt;T&gt;

        一个简单的实现:

        
        function later(delay) {
          return {
            then(onResolve, onReject) {
              return new Promise(resolve => {
                console.log("called new Promise()");
                setTimeout(resolve, delay);
              }).then(onResolve, onReject);
            }
          }
        }
        

        但是对于这个用例,我们可以完全摆脱 Promise:

        function later(delay) {
          return {
            then(onResolve) {
              console.log("called setTimeout()");
              setTimeout(onResolve, delay);
            }
          }
        }
        

        这个实现假设你最多调用later(n).then(...),就像await 一样。但不是later(n).then(...).then(...)catch()finally() 或所有爵士乐。如果您想要所有这些,请使用返回 Promise

        的实现

        function later(delay) {
          return {
            then(onResolve) {
              console.log("called setTimeout()");
              setTimeout(onResolve, delay);
            }
          }
        }
        
        const action = later(1000);
        
        console.log("obj created");
        
        // wait a bit so that its clear that new Promise ain't called immediately
        setTimeout(async() => {
          console.log("before awaiting");
          await action;
          console.log("after awaiting");
        
          await action;
          console.log("awaiting the same object a second time");
        
          await action;
          console.log("and a third time");
        
          await later(3000); // also works
        
          console.log("done");
        
        }, 2000);
        .as-console-wrapper{top:0;max-height:100%!important;}

        【讨论】:

          猜你喜欢
          • 2019-04-29
          • 2019-05-23
          • 1970-01-01
          • 1970-01-01
          • 2018-11-20
          • 2015-11-10
          • 2015-11-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多