为什么当我不等待时这个承诺会解决

Why does this promise resolve when I am not awaiting it

我有以下承诺,但如果我 运行 ts playground 中的这段代码,它似乎不用我等待就解决了。

const promises = [later(1000)];


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

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

await Promise.all(promises);

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

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

(请注意,这与 操作的可观察对象不同,订阅它们会调用它们)

正如其他 posts/comments 所说,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()));

然后是thenables;在打字稿中 PromiseLike<T>.

一个简单的实现:


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() 或所有爵士乐。如果你想要所有这些,请使用 returns a 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;}