I started diggin\' in promises and found interesting Promise.all.
It is stated in MDN that
The Promise.all(iterable) method returns a promise
The Promise.all(iterables) function returns a single Promise.Here we provide multiple Promises as argument. Promise.all(iterables) function returns promise only when all the promises (argument) have resolved. It rejects when first promise argument reject.
var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
// expected output: Array [3, 42, "foo"]
});
Syntax:
Promise.all(func1, func2 [,funcN])
Parameters:
Read more at - https://www.oodlestechnologies.com/blogs/An-Introduction-To-Promise.all-Function
Your get
function returns a Promise
. You are just passing a reference to the get
function. You have to pass an array of Promises
Promise.all([get("one.jpg")]).then(...);
TLDR:
Promise.all
is a Javascript method that takes an iterable (e.g. Array
) of promises as an argument and returns a single promise when all the promises in the iterable argument have been resolved (or when iterable argument contains no promises). It resolves with an array of the resolved values and rejects with a single value of the first rejected Promise.
var promise1 = Promise.resolve(5);
var promise2 = Math.random() > 0.5? 1 : Promise.reject(1); // either resolves or rejects
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => resolve('foo'), 1000);
});
Promise.all([promise1, promise2, promise3]).then((val) => {
console.log(val);
}).catch((val) => {
console.log(val);
});
In the above example 3 Promises are passed into the Promise.all
function as an array. Promise 1 and 3 always resolve. Promise 2 either resolves or rejects based on the random Nr generator. This Promise.all method then returns a resolved or rejected Promise based on the random Nr generator.
Then the then()
method and the catch()
method can be called on this promise which is returned from Promise.all
. The then()
method gets an array of all the resolved values, [5, 1, 'foo']
in this case. The catch()
method gets the value of the first rejected Promise, 1
in this example.
This method is very usefull when you want to execute multiple async operations and need to something with the results after the async operations. When using Promise.all
all promises can be processed at the same time while still getting to operate on all the incoming data.
For example, when we need to get information using multiple AJAX requests and combine the data to something useful. It is essential to wait for all the data to be available otherwise we would try to combine non existing data which would lead to problems.
Promise.all
takes an array (or any iterable) of promises and fulfills when all of them fulfill or rejects when one of them rejects. I think it's easier to understand if we implement it and understand why we need it.
A common use case might be to wait for the window to load and for the server to return data in order to run some code:
// a function that returns a promise for when the document is ready.
function windowReady(){
return new Promise(function(resolve){
window.addEventListener('DOMContentLoaded', resolve);
});
}
// function that returns a promise for some data
function getData(){
return fetch("/").then(function(r){ return r.json() });
}
Now, we want both of them to execute at the same time and then get the result. There are two items here but there could have easily been 5 things to wait for, or 100. So we use Promise.all
:
Promise.all([windowReady(), getData()]).then(function(results){
// results[1] is the data, it's all in an array.
});
Let's see how we can implement it:
function all(iterable){ // take an iterable
// `all` returns a promise.
return new Promise(function(resolve, reject){
let counter = 0; // start with 0 things to wait for
let results = [], i;
for(let p of iterable){
let current = i;
counter++; // increase the counter
Promise.resolve(p).then(function(res){ // treat p as a promise, when it is ready:
results[i] = res; // keep the current result
if(counter === 0) resolve(results) // we're done
}, reject); // we reject on ANY error
i++; // progress counter for results array
}
});
}
Or, in even more ES6ness:
let all = iterable => new Promise((resolve, reject) => {
let arr = [...iterable], c = arr.length, results = [];
arr.map(Promise.resolve, Promise).
map((p, i) => p.then(v => {
r[i] = v;
if(--c === 0) resolve(r);
} , reject));
});