如何在 Promisification [duplicate] 后取消“setTimeout”

How to cancel `setTimeout` after Promisification [duplicate]

提问人:rostamiani 提问时间:10/4/2023 最后编辑:Bergirostamiani 更新时间:10/4/2023 访问量:72

问:

我使用 setTimeout 作为 Promise。但是我不能使用 .这是我的代码:clearTimeout

const delay = (ms) => new Promise((res) => setTimeout(res, ms));
delay(1000).then(() => console.log("Done"));

但是使用这种方法,我无法使用 clearTimeout 取消超时。 我尝试了nestjs函数,但仍然无法做到这一点promisify

JavaScript 节点 .js 设置超时 ES6-promise 取消

评论

0赞 Helge Derenthal 10/4/2023
你的零件是什么样子的?clearTimeout
0赞 jonrsharpe 10/4/2023
你不能,正如所写的那样,你需要返回一些东西,比如一个延迟的对象,或者一个 然后能够 用其他方法进行取消等。

答:

1赞 harsh Kanodiya 10/4/2023 #1

要使用 Promise 创建可取消的延迟,您可以以一种允许您跟踪超时 ID 的方式包装 setTimeout,然后在需要时使用该 ID 取消超时。下面是如何做到这一点的示例:

class CancelablePromiseDelay {
constructor(ms) {
this.ms = ms;
this.timeoutId = null;
this.promise = new Promise((resolve, reject) => {
  this.resolve = resolve;
  this.reject = reject;
  this.timeoutId = setTimeout(() => {
    resolve();
    this.timeoutId = null;
  }, ms);
  });
 }

  cancel() {
   if (this.timeoutId !== null) {
  clearTimeout(this.timeoutId);
  this.timeoutId = null;
  this.reject(new Error('Delay canceled'));
   }
  }
   }

     const delay = (ms) => new CancelablePromiseDelay(ms);

   const delayPromise = delay(1000);

     delayPromise
  .then(() => console.log('Done'))
     .catch((error) => console.error(error));

 // To cancel the delay
  // delayPromise.cancel();

评论

1赞 Mario Santini 10/4/2023
值得一提的是,如果你忘了拒绝承诺,一旦你取消了 setTimeout 任务,你就会永远等待。另一点是强制使用 catch,或者 a 以避免在取消 setTimeout 时出错。try {} catch() {}
4赞 Bergi 10/4/2023 #2

您不能从外部取消承诺。在创建 promise 时,您需要决定何时以及如何解决 promise。要取消任务(在本例中为计时器),请传递取消信号作为参数。

您不必使用 和 ,也不必承诺它们。相反,只需使用已提供此功能的 node:timers/promise 中的内置 setTimeoutsetTimeoutclearTimeout

const { setTimeout } = require('node:timers/promises');

const ac = new AbortController();
const signal = ac.signal;

setTimeout(1000, 'foobar', { signal })
  .then(console.log)
  .catch((err) => {
    if (err.name === 'AbortError')
      console.error('The timeout was aborted');
  });

ac.abort();

如果您想自己实现这一点,请参阅此答案的示例。