Skip to content

Instantly share code, notes, and snippets.

@arvi
Forked from indiesquidge/promise-dot-all.js
Created April 23, 2018 05:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arvi/01697f45b78ad03a036580a47326af77 to your computer and use it in GitHub Desktop.
Save arvi/01697f45b78ad03a036580a47326af77 to your computer and use it in GitHub Desktop.
Recreating Promise.all with async/await
/*
Let us re-create `Promise.all`
`Promise.all` method returns a promise that resolves when all of the promises in the iterable argument have resolved,
or rejects with the reason of the first passed promise that rejects.
Read more about `Promise.all` on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
A basic example would be something like this:
Promise.all([promise1, promise2, promise3])
.then(allResolvedData => console.log('here are the resolutions to the promises', allResolvedData))
*/
let allWithAsync = (...listOfPromises) => {
return new Promise(async resolve => {
let results = []
for (let promise of listOfPromises) {
results.push(await promise.then(async resolvedData => await resolvedData))
if (results.length === listOfPromises.length) resolve(results)
}
})
}
const promise1 = Promise.resolve('first')
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 1000, 'second'))
const promise3 = Promise.resolve('third')
allWithAsync(promise1, promise2, promise3)
.then(resolvedData => {
console.log(resolvedData) // ['first', 'second', 'third']
})
/*
This is good, and it returns our promise resolutions in the right order,
but what happens if our list includes something that is not a promise?
*/
const promise4 = 'promise4'
/*
This will break our current `allWithAsync` by telling us that `promise.then` is not a function for our new `promise4`.
We can fix this with a small change to our function that wraps all items in the `listOfPromises` in a `Promise.resolve`.
Doing this will return each item as a promise that is resolved with said item.
*/
allWithAsync = (...listOfPromises) => {
return new Promise(async resolve => {
let results = []
for (let promise of listOfPromises.map(Promise.resolve, Promise)) {
results.push(await promise.then(async resolvedData => await resolvedData))
if (results.length === listOfPromises.length) resolve(results)
}
})
}
allWithAsync(promise1, promise2, promise3, promise4)
.then(resolvedData => {
console.log(resolvedData) // ['first', 'second', 'third', 'fourth']
})
/*
This is looking pretty good. One last thing: rejection handling.
*/
const promise5 = Promise.reject('rejected!')
/*
As mentioned above, `Promise.all` will either return a promise that resolves when all of the promises in
the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects.
Let's handle the rejection case.
So far, our `Promise.then` has only been dealing with the fulfillment scenario of each promise.
A quick look at the API shows us that `Promise.then` can take two arguments: a fulfillment and a rejection handler.
Notice that we are returning a new Promise from our function. `new Promise` takes a callback with two arguments.
We are using one right now: `resolve`. But the second argument is `reject`.
If we include this in our promise instantiation callback and call it in our `Promise.then` function,
we should get the error handling we are looking for!
*/
allWithAsync = (...listOfPromises) => {
return new Promise(async (resolve, reject) => {
let results = []
for (let promise of listOfPromises.map(Promise.resolve, Promise)) {
results.push(await promise.then(async resolvedData => await resolvedData, reject))
if (results.length === listOfPromises.length) resolve(results)
}
})
}
allWithAsync(promise1, promise2, promise3, promise4, promise5)
.then(resolvedData => {
console.log(resolvedData) // will not run since we have a rejection!
}, rejectionReason => console.log('reason:', rejectionReason)) // reason: rejected!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment