Monday, May 13, 2024
 Popular · Latest · Hot · Upcoming
176
rated 0 times [  178] [ 2]  / answers: 1 / hits: 15910  / 10 Years ago, sun, august 17, 2014, 12:00:00

I'm toying with promises in JavaScript and tried to promisify setTimeout function:



function timeout(ms) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('timeout done');
}, ms);
});
}

var myPromise=timeout(3000);

myPromise.then(function(result) {
console.log(result); // timeout done
})


Fairly straightforward but I was wondering how would I go about canceling my timeout before the promise resolves. timeout returns Promise object hence I loose access to value that setTimeout returns and cannot cancel timeout via clearTimeout. What woud be the best way to do it?



BTW there is no real purpose for this, I just wonder how this would be approached. Also I plunked it here http://plnkr.co/edit/NXFjs1dXWVFNEOeCV1BA?p=preview


More From » promise

 Answers
6

Edit 2021 all platforms have converged on AbortController as the cancellation primitive and there is some built in support for this.


In Node.js


// import { setTimeout } from 'timers/promises' // in ESM
const { setTimeout } = require('timers/promises');
const ac = new AbortController();

// cancellable timeout
(async () => {
await setTimeout(1000, null, { signal: ac.signal });
})();

// abort the timeout, rejects with an ERR_ABORT
ac.abort();

In Browsers


You can polyfill this API and use the same as the example above:



function delay(ms, value, { signal } = {}) {
return new Promise((resolve, reject) => {
const listener = () => {
clearTimeout(timer);
reject(signal.reason);
};
signal?.throwIfAborted();
const timer = setTimeout(() => {
signal?.removeEventListener('abort', listener);
resolve(value);
}, ms);
signal?.addEventListener('abort', listener);
});
}



What you can do it that, you can return a canceller from your timeout function and invoke it when needed. This way you do not need to store the timeoutid globally (or on the outer scope) and also this can manage multiple calls to the function as well. Each instance of the object return by the function timeout will have its own canceler that can perform the cancellation.


function timeout(ms) {
var timeout, promise;

promise = new Promise(function(resolve, reject) {
timeout = setTimeout(function() {
resolve('timeout done');
}, ms);
});

return {
promise:promise,
cancel:function(){clearTimeout(timeout );} //return a canceller as well
};
}

var timeOutObj =timeout(3000);

timeOutObj.promise.then(function(result) {
console.log(result); // timeout done
});

//Cancel it.
timeOutObj.cancel();

Plnkr


[#69753] Thursday, August 14, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
warren

Total Points: 679
Total Questions: 115
Total Answers: 78

Location: Antigua and Barbuda
Member since Sat, Apr 24, 2021
3 Years ago
;