skip to Main Content

I’m using setTimeout as a Promise. But then I cannot cancel it using clearTimeout. THis is my code:

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

But using this approach I cannot cancel timeout using clearTimeout.
I tried promisify nestjs function but still cannot do this

2

Answers


  1. To create a cancelable delay using Promises, you can wrap setTimeout in a way that allows you to keep track of the timeout ID and then use that ID to cancel the timeout if needed. Here’s an example of how you can do it:

    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();
    
    Login or Signup to reply.
  2. You cannot cancel a promise from outside. You need to decide when and how the promise should be resolved when you create the promise. To cancel the task (in this case, the timer), pass a cancellation signal as an argument.

    You don’t have to use setTimeout and clearTimeout, and you don’t have to promisify them. Instead, just use the builtin setTimeout from node:timers/promises that already provides this functionality:

    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();
    

    If you want to implement this yourself, see this answer for an example.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search