Skip to content

Instantly share code, notes, and snippets.

@coffee-mug
Created March 15, 2018 14:04
Show Gist options
  • Save coffee-mug/84fbef02e16379d002a768746d27045f to your computer and use it in GitHub Desktop.
Save coffee-mug/84fbef02e16379d002a768746d27045f to your computer and use it in GitHub Desktop.
Chain promises in JS
// Promises, the big deal
// Here's a, a small function that returns a promise,
// which resolves itself at a random time between 0 and 1/2s, returning "My question num"
var a = (num) => {
return new Promise( (res, rej) => {
// return "My question num" between immediately and 1/2 s.
return setTimeout( () => res(`My question ${num}`), 500 * Math.random())
})
}
// Now imagine that we want to log a list of questions, that are all being received at a random
// time between 0 and 1/2s (our function a actually) in order (like question 1 then 2 then 3 then 4)
// The first naive way of doing it could be to do:
[1,2,3,4].map(a).forEach(promise => promise.then(question => console.log(`%c ${question}`, 'color: red') ))
// We create a list of promises through passing each number to the a function above (map(a))
// and then, we execute each promise with then, get the question that has been resolved and log it.
// Unfortunately, it won't display them in order (printed in red in the console if you open it)
// To keep the order (chaining) we have to :
// 1 set a promise
// 2 execute it with .then(result => result)
// 3 inside the then, create the next promise to call
// (to force it to be executed after the first promise)
// chain function does exactly that, using recursion.
// Good free book to understand recursion in JS: https://leanpub.com/javascriptallongesix/read
// ITS FREE, ONLINE, IN JAVASCRIPT
var chain = ([f, ...rest]) => {
// [f, ...rest] is called destructuring assignment: it expects a list as an argument
// and will automatically bind f to the first element of the list and rest to the
// remaining elements of the list. Useful for recursion.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
if (rest.length == 0) {
// Stop recursion condition: if there is no more arguments than one to which we can apply the function
// Then, we simply execute it one more time on this element and return to stop the recursion.
return a(f).then(q => console.log(q));
}
// we apply the function a, which returns a promise, log the resolved result to the console
// and recurse on remaining elements.
return a(f).then(q => { console.log(q); return chain([...rest]) });
}
/* Should output in the console
* My question 1
* My question 2
* My question 3
* My question 4
* My question 5
**/
chain([1,2,3,4,5,6]);
/** Good references to master all of this
* Javascript allongé, le meilleur livre sur le JS et la programmation fonctionnelle, version ES5 ou ES6.
https://leanpub.com/javascriptallongesix/read
* Chaining promises with reduce - MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Running_Promises_in_Sequence
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment