Instantly share code, notes, and snippets.

Embed
What would you like to do?
Promise protips - stuff I wish I had known when I started with Promises
// Promise.all is good for executing many promises at once
Promise.all([
promise1,
promise2
]);
// Promise.resolve is good for wrapping synchronous code
Promise.resolve().then(function () {
if (somethingIsNotRight()) {
throw new Error("I will be rejected asynchronously!");
} else {
return "This string will be resolved asynchronously!";
}
});
// execute some promises one after the other.
// this takes an array of promise factories, i.e.
// an array of functions that RETURN a promise
// (not an array of promises themselves; those would execute immediately)
function sequentialize(promiseFactories) {
var chain = Promise.resolve();
promiseFactories.forEach(function (promiseFactory) {
chain = chain.then(promiseFactory);
});
return chain;
}
// Promise.race is good for setting a timeout:
Promise.race([
new Promise(function (resolve, reject) {
setTimeout(reject, 10000); // timeout after 10 secs
}),
doSomethingThatMayTakeAwhile()
]);
// Promise finally util similar to Q.finally
// e.g. promise.then(...).catch().then(...).finally(...)
function finally (promise, cb) {
return promise.then(function (res) {
var promise2 = cb();
if (typeof promise2.then === 'function') {
return promise2.then(function () {
return res;
});
}
return res;
}, function (reason) {
var promise2 = cb();
if (typeof promise2.then === 'function') {
return promise2.then(function () {
throw reason;
});
}
throw reason;
});
};
@reggi

This comment has been minimized.

Show comment
Hide comment
@reggi

reggi Apr 23, 2015

Is there a extra ) on line 12?

reggi commented Apr 23, 2015

Is there a extra ) on line 12?

@nolanlawson

This comment has been minimized.

Show comment
Hide comment
@nolanlawson

nolanlawson Apr 23, 2015

yup, got it :)

Owner

nolanlawson commented Apr 23, 2015

yup, got it :)

@robertd

This comment has been minimized.

Show comment
Hide comment
@robertd

robertd May 19, 2015

Brilliant gist! Thanks!

robertd commented May 19, 2015

Brilliant gist! Thanks!

@RinatMullayanov

This comment has been minimized.

Show comment
Hide comment
@RinatMullayanov

RinatMullayanov commented May 21, 2015

awesome

@alirezaDavid

This comment has been minimized.

Show comment
Hide comment
@alirezaDavid

alirezaDavid May 22, 2015

thanks a lot man :)

alirezaDavid commented May 22, 2015

thanks a lot man :)

@soundyogi

This comment has been minimized.

Show comment
Hide comment
@soundyogi

soundyogi Jul 11, 2015

Your Article on PouchDB brought me here.
One of the best I have read this year.
Brilliant Gist aswell.

Thank you very much :)

soundyogi commented Jul 11, 2015

Your Article on PouchDB brought me here.
One of the best I have read this year.
Brilliant Gist aswell.

Thank you very much :)

@sharkySharks

This comment has been minimized.

Show comment
Hide comment
@sharkySharks

sharkySharks Jul 20, 2015

^ ditto, great article and examples!

sharkySharks commented Jul 20, 2015

^ ditto, great article and examples!

@asicfr

This comment has been minimized.

Show comment
Hide comment
@asicfr

asicfr Jul 24, 2015

thanks for the article and cool examples

asicfr commented Jul 24, 2015

thanks for the article and cool examples

@mgtitimoli

This comment has been minimized.

Show comment
Hide comment
@mgtitimoli

mgtitimoli Oct 4, 2015

Great gist (got here from your also great article)!
Your example that uses Promise.race to define a new promise with a timeout on an promised operation is just AMAZING!

mgtitimoli commented Oct 4, 2015

Great gist (got here from your also great article)!
Your example that uses Promise.race to define a new promise with a timeout on an promised operation is just AMAZING!

@parvezapathan

This comment has been minimized.

Show comment
Hide comment
@parvezapathan

parvezapathan Oct 30, 2015

A very useful article and then this awesome gist !
THANK YOU !

parvezapathan commented Oct 30, 2015

A very useful article and then this awesome gist !
THANK YOU !

@khanghoang

This comment has been minimized.

Show comment
Hide comment
@khanghoang

khanghoang Oct 31, 2015

👍 you're my hero.

khanghoang commented Oct 31, 2015

👍 you're my hero.

@nickhudkins

This comment has been minimized.

Show comment
Hide comment
@nickhudkins

nickhudkins Nov 2, 2015

Promise.race is the neatest timeout implementation ever.

nickhudkins commented Nov 2, 2015

Promise.race is the neatest timeout implementation ever.

@Webbrother

This comment has been minimized.

Show comment
Hide comment
@Webbrother

Webbrother Nov 8, 2015

God bless you!

Webbrother commented Nov 8, 2015

God bless you!

@Williammer

This comment has been minimized.

Show comment
Hide comment
@Williammer

Williammer Jan 8, 2016

Thanks for the Blog post on Promise, really enlightened my understanding on it!

Williammer commented Jan 8, 2016

Thanks for the Blog post on Promise, really enlightened my understanding on it!

@bruceharris

This comment has been minimized.

Show comment
Hide comment
@bruceharris

bruceharris Jan 13, 2016

@nolanlawson nice gist, good stuff, thanks. In lieu of a PR, suggestion to streamline sequentialize with reduce, per my fork https://gist.github.com/bruceharris/8c9e6829c9f65ab33f31/revisions

bruceharris commented Jan 13, 2016

@nolanlawson nice gist, good stuff, thanks. In lieu of a PR, suggestion to streamline sequentialize with reduce, per my fork https://gist.github.com/bruceharris/8c9e6829c9f65ab33f31/revisions

@damned

This comment has been minimized.

Show comment
Hide comment
@damned

damned Feb 8, 2016

great article, keep up the good work, thanks :)

damned commented Feb 8, 2016

great article, keep up the good work, thanks :)

@sanfordstaab

This comment has been minimized.

Show comment
Hide comment
@sanfordstaab

sanfordstaab Feb 29, 2016

I knew when I started learning promises a few days ago that I needed them and that I just didn't get them. Your article certainly helped me a lot to 'begin-to-get' them. I think after several re-reads I will finally 'get' them.
Something in the back of my head says this could be better. I look forward to the ES7 improvements you mention but something tells me there is still a yet better way to do promises without needing language enhancements. If I do figure out a better way, I will let you know.

... ps
THANKS MAN!!!!

sanfordstaab commented Feb 29, 2016

I knew when I started learning promises a few days ago that I needed them and that I just didn't get them. Your article certainly helped me a lot to 'begin-to-get' them. I think after several re-reads I will finally 'get' them.
Something in the back of my head says this could be better. I look forward to the ES7 improvements you mention but something tells me there is still a yet better way to do promises without needing language enhancements. If I do figure out a better way, I will let you know.

... ps
THANKS MAN!!!!

@dev-rowbot

This comment has been minimized.

Show comment
Hide comment
@dev-rowbot

dev-rowbot Sep 29, 2016

Great article on pouchdb, really helped me out a lot.

I have a question on the promise factory and chain example. Is there any way that I can I get the result from each step? Similar to how a Q.all() would operate. I'll clarify with my use case - I have a list of Nuget Packages that I am trying to delete, for each package I need to make an HTTP DELETE request.

I initially used Q.all() but soon realised that this was sending all 500 requests at once - this is not ideal. Using your promise factories example I was able to add a delay between each request - very useful. But unfortunately the data returned in the HTTP request resolve() is lost.
Having the resolve data is not critical since a reject will break the chain and I can handle the error, so my question is really just so I can learn how to handle this situation.

My Code for reference

Q.when(genericKlondikeQuery(query, 'GET')).then(function (parsed) {
    // logic for cleaning up the results
    // ....
    function packageDeletionFactory(id, version) {
        return Q.delay(250).then(function () {
            console.log('Deleting Package: ' + id + '/' + version);
            return genericKlondikeQuery('/api/packages/' + id + '/' + version, 'DELETE');
        });
    }
    // Promise Chain
    var result = Q();
    hits.forEach(function (element) {
        result = result.then(function () {
            return packageDeletionFactory(element.id, element.version);
        });
    });
    return result;

}).then(function (results) {
    // results == the result from the last chain link
    done();
}).catch(console.log.bind(console));

dev-rowbot commented Sep 29, 2016

Great article on pouchdb, really helped me out a lot.

I have a question on the promise factory and chain example. Is there any way that I can I get the result from each step? Similar to how a Q.all() would operate. I'll clarify with my use case - I have a list of Nuget Packages that I am trying to delete, for each package I need to make an HTTP DELETE request.

I initially used Q.all() but soon realised that this was sending all 500 requests at once - this is not ideal. Using your promise factories example I was able to add a delay between each request - very useful. But unfortunately the data returned in the HTTP request resolve() is lost.
Having the resolve data is not critical since a reject will break the chain and I can handle the error, so my question is really just so I can learn how to handle this situation.

My Code for reference

Q.when(genericKlondikeQuery(query, 'GET')).then(function (parsed) {
    // logic for cleaning up the results
    // ....
    function packageDeletionFactory(id, version) {
        return Q.delay(250).then(function () {
            console.log('Deleting Package: ' + id + '/' + version);
            return genericKlondikeQuery('/api/packages/' + id + '/' + version, 'DELETE');
        });
    }
    // Promise Chain
    var result = Q();
    hits.forEach(function (element) {
        result = result.then(function () {
            return packageDeletionFactory(element.id, element.version);
        });
    });
    return result;

}).then(function (results) {
    // results == the result from the last chain link
    done();
}).catch(console.log.bind(console));
@akanshgulati

This comment has been minimized.

Show comment
Hide comment
@akanshgulati

akanshgulati Sep 30, 2016

@nolanlawson Can you explain how the above factory promise is working in depth. It will help many developers.

akanshgulati commented Sep 30, 2016

@nolanlawson Can you explain how the above factory promise is working in depth. It will help many developers.

@Jeff-Walker

This comment has been minimized.

Show comment
Hide comment
@Jeff-Walker

Jeff-Walker Mar 13, 2017

@nolanlawson
Sorry if I've missed the point, but finally() isn't a function on the Promise type, so the example in the comment doesn't work. So, how do you use it? Wrap the whole thing in the function call? Kinda kills the beauty of the promise chain. Add it to the Promise prototype?

Thanks.

Jeff-Walker commented Mar 13, 2017

@nolanlawson
Sorry if I've missed the point, but finally() isn't a function on the Promise type, so the example in the comment doesn't work. So, how do you use it? Wrap the whole thing in the function call? Kinda kills the beauty of the promise chain. Add it to the Promise prototype?

Thanks.

@owendall

This comment has been minimized.

Show comment
Hide comment
@owendall

owendall Aug 11, 2017

Great Article!

owendall commented Aug 11, 2017

Great Article!

@ridespirals

This comment has been minimized.

Show comment
Hide comment
@ridespirals

ridespirals Oct 31, 2017

Here's a tip for if you want to use Promise.all but want something nicer than an array to hold the final values:

Promise.all({
    foo: doSomething(),
    bar: doSomethingElse(),
    quux: doAnotherThing().then(q => q.property)
}).then(values => {
    const { foo, bar, quux } = values
    // now you have the result of foo, bar, and quux (including the transformation on quux from the "then" that it had)
})

ridespirals commented Oct 31, 2017

Here's a tip for if you want to use Promise.all but want something nicer than an array to hold the final values:

Promise.all({
    foo: doSomething(),
    bar: doSomethingElse(),
    quux: doAnotherThing().then(q => q.property)
}).then(values => {
    const { foo, bar, quux } = values
    // now you have the result of foo, bar, and quux (including the transformation on quux from the "then" that it had)
})
@goyanx

This comment has been minimized.

Show comment
Hide comment
@goyanx

goyanx Feb 3, 2018

nice article!

goyanx commented Feb 3, 2018

nice article!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment