Johnny Oshika
Johnny Oshika

Reputation: 57502

Promise: chained timeout

The Promise API doesn't have a chainable timeout option, but in Steve Sanderson's presentation at NDC Conference (at 15:31 here https://www.youtube.com/watch?v=9G8HEDI3K6s&feature=youtu.be&t=15m31s), he presented an elegant chainable timeout on the fetch API. It looks like this:

enter image description here

The great thing about this approach is that the resolve handler still completed (e.g. the response was still put into cache) even after the timeout. He demo'd this during his presentation (and available at the YouTube link above). Anyone know how this chainable timeout was implemented?

Upvotes: 4

Views: 150

Answers (1)

Ashley Davis
Ashley Davis

Reputation: 10040

I usually use Promise.race to implement timeouts. Normally I haven't tried to make this chainable, but that's a cool idea so I'll give it a go in a moment.

This is how I'd normally use it to implement a timeout:

function timeout (promise, duration) {
    return Promise.race([
        promise,
        new Promise((resolve, reject) => {
            setTimeout(
                () => reject(new Error("Timeout")), 
                duration
            )
        })
    ]);
} 

timeout(fetch("something"), 5000)
    .then(() => {
        // ... Operation completed without timeout ...
    })
    .catch(err => {
        // ... An error occurred possibly a timeout ...
    ));

You might be able to make this chainable by attaching your function to the prototype of the Promise class (maybe depending on which promise library you are actually using):

Promise.prototype.timeout = function (duration) {
    return Promise.race([
        this,
        new Promise((resolve, reject) => {
            setTimeout(
                () => reject(new Error("Timeout")), 
                duration
            )
        })
    ]);
};

fetch("something")
    .then(() => ...) // This executes before the timeout.
    .timeout(5000)
    .catch(err => ...);

Upvotes: 1

Related Questions