Tao P. R. Tao P. R. - 3 months ago 6
Javascript Question

What is the best general practice to timeout a function in promise

Promisify a function call with timeouts

I have seen many resources provide similar examples of using

Promise.race
to timeout a function call within a given period of time. This is a very good example of how
Promise.race
can be used in practice. Here's some sample code:

function doWithinInterval(func, timeout) {
var promiseTimeout = new Promise(function (fulfill, reject) {
// Rejects as soon as the timeout kicks in
setTimeout(reject, timeout);
});
var promiseFunc = new Promise(function (fulfill, reject) {
var result = func(); // Function that may take long to finish
// Fulfills when the given function finishes
fulfill(result);
});

return Promise.race([promiseTimeout, promiseFunc]);
}


The simple approach above using
Promise.race
rejects the promise as soon as the timeout kicks in before
func
has completed. Otherwise, the project is fulfilled once the
func
function finishes before the timeout interval.

This sounds good and easy to use.

However, is this the best practice to use timeout in Promise?

Surely, the approach above can be employed if we want to set a timeout against a function call using Promises. The operations still appear to be a good promise. However, is this considered a good practice of using timeout in a Promise? If not, what is the disadvantage of using this?

I've look for alternative approaches, but couldn't find a native Promise way to do this.

Instead, some external Promise libraries offer
timeout
functionality as follows:



However,
Promise.timeout()
doesn't appear to be part of the standard ECMAScript 6 API (please correct me if I'm wrong). Is there any recommended way to handle timeouts natively with ES6 Promises?

jib jib
Answer

It depends on what you mean by timeout.

If you expect the function to stop, then no.

If you just want to stop waiting for it, then yes (quick to whip up in ES6):

var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var timeout = (p, ms) => Promise.race([p, wait(ms).then(() => {
    throw new Error("Timeout after " + ms + " ms");
})]);

var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var timeout = (p, ms) => Promise.race([p, wait(ms).then(() => {
  throw new Error("Timeout after " + ms + " ms");
})]);

// Example:

var log = msg => div.innerHTML += "<p>" + msg + "</p>";
var failed = e => log(e.toString() + ", line " + e.lineNumber);

log("Waiting 5 seconds...");
timeout(wait(5000), 2000)
.then(() => log("...Done."))
.catch(failed);
<div id="div"></div>

If you want to cancel the operation (make it stop), then hopefully that operation comes with an API to cancel it, and you should use that, since an ES6 promise is not a control surface.

Cancelable promises is a controversial topic in ES6, but some of the libraries mentioned do offer the concept.