Skip to content

Instantly share code, notes, and snippets.

@nolanlawson
Last active August 22, 2024 14:19
Show Gist options
  • Save nolanlawson/6ce81186421d2fa109a4 to your computer and use it in GitHub Desktop.
Save nolanlawson/6ce81186421d2fa109a4 to your computer and use it in GitHub Desktop.
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;
});
};
@Webbrother
Copy link

God bless you!

@Williammer
Copy link

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

@bruceharris
Copy link

@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
Copy link

damned commented Feb 8, 2016

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

@sanfordstaab
Copy link

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
Copy link

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
Copy link

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

@Jeff-Walker
Copy link

@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
Copy link

Great Article!

@ridespirals
Copy link

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
Copy link

goyanx commented Feb 3, 2018

nice article!

@JestVA
Copy link

JestVA commented Jan 13, 2019

Great article, still a rookie to understand promises and make useful application of the concepts.

@xgqfrms
Copy link

xgqfrms commented Nov 16, 2020

👍 awesome promise article

@delbaredouard
Copy link

delbaredouard commented Jan 17, 2022

Thanks for that :-D

putYourRightFootIn()
  .then(putYourRightFootOut)
  .then(putYourRightFootIn)  
  .then(shakeItAllAbout);

Taken from your enlightening easy to read blog post.

@JanithaR
Copy link

What's a good use case for wrapping synchronous code with a Promise?

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