Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set maximum execution time for a Promise await?

Tags:

javascript

How would you wait for a Promise to resolve/reject, for a maximum execution time ? The code below is obviously wrong, it's just to explain what I'm trying to achieve. I'm clueless.

await doSomething();
if ( executionTime > maxExecutionTime ) {
    doSomethingElse();
}

This is not for a bluebird promise.

like image 945
standac Avatar asked Dec 08 '17 16:12

standac


People also ask

How do I set timeout on promise?

The built-in function setTimeout uses callbacks. Create a promise-based alternative. function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } delay(3000).

How do I add a timeout to async?

In order to create the timeout, we will use an asynchronous function that takes in a Promise, as well as a time limit. Since JavaScript's native setTimeout function uses milliseconds as a parameter, we will use the same to keep things simple. const asyncCallWithTimeout = (asyncPromise, timeLimit) => {};

How long does await wait for?

Basically, forever. Also the await doesn't hold up anything.

Does execution stop at await?

The await expression causes async function execution to pause until a promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment.


2 Answers

You can use Promise.race() which will immediately resolve/reject when the first promise in its iterable resolves or rejects. E.g.

   
const longTask = () => new Promise(resolve =>
  setTimeout(() => resolve("Long task complete."), 300))

const timeout = (cb, interval) => () =>
  new Promise(resolve => setTimeout(() => cb(resolve), interval))

const onTimeout = timeout(resolve =>
  resolve("The 'maybeLongTask' ran too long!"), 200)

Promise.race([longTask, onTimeout].map(f => f())).then(console.log)

The only issue is you can't really cancel the 'longTask' just because of its long execution. In theory, you'd either set some flag (to tell it not to continue onto the next stage of its pipeline), or design your application with the consequences of the promise in mind.

See what happens when you swap the 200 and 300 intervals.

Edit: Per spsaucier's comment, I've delayed the execution of each promise until the Promise.line line.

like image 133
noahnu Avatar answered Oct 05 '22 23:10

noahnu


The code below will give you some idea:

function doSomething(maxExecutionTime) {
    return new Promise(resolve => {
        setTimeout(() => resolve(true), 2000);  // this setTimeout simulates your async action which sould not exced maxExecutionTime
        setTimeout(() => resolve(false), maxExecutionTime);
    });
}

async function someFunc(maxExecutionTime) {
    var exced = await doSomething(maxExecutionTime);
    if (exced) {
        console.log("Doesn't exced max time");
    } else {
        console.log("Exced max time");
    }
}

someFunc(1000);
someFunc(3000);
like image 34
Faly Avatar answered Oct 05 '22 23:10

Faly