I want to fetch multiple images and turn them in blob. I'm a newbie about promises, I've tried but I can't get through.
Here below, a single .fetch()
promise
fetch('http://cors.io/?u=http://alistapart.com/d/_made/d/ALA350_appcache_300_960_472_81.jpg')
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
document.getElementById('myImage').src = objectURL;
});
Now multiple .fetch()
promise (don't work)
var promises = [];
for (var i = values.length - 1; i >= 0; i--) {
promises.push(fetch(values[i]));
}
Promise
.all(promises)
.then(function(response) {
for (var i = response.length - 1; i >= 0; i--) {
return response[i].blob();
}
})
.then(function(blob) {
console.log(blob.length); //undefined !!!
for (var i = blob.length - 1; i >= 0; i--) {
console.log(blob[i]);
lcl_images[i].value = URL.createObjectURL(blob[i]);
document.getElementById(lcl_images[i].id).src = objectURL;
}
})
.catch(function(error) {
console.log(error);
});
fetch() The global fetch() method starts the process of fetching a resource from the network, returning a promise which is fulfilled once the response is available. The promise resolves to the Response object representing the response to your request.
To do multiple fetch requests in parallel, we can use the all() method from the global Promise object in JavaScript.
The fetch() method in JavaScript is used to request data from a server. The request can be of any type of API that return the data in JSON or XML. The fetch() method requires one parameter, the URL to request, and returns a promise.
It is a general rule that a wholly synchronous intermediate step in the success path of a promise chain can be amalgamated with the next step, allowing one then()
to be omitted from the chain.
There is actually a proviso on that statement, involving intermediate catches, but it will suffice for this answer.
So, if the .blob()
method is geuinely synchronous (it returns a value), only one .then()
is required, not two.
Here are two approaches, both of which exploit Array.prototype.map(), and both should work (though they will differ under error conditions):
1. Simple .map()
with detail in Promise.all()
var promises = values.reverse().map(fetch); // you may need .reverse(), maybe not. I'm not 100% sure.
return Promise.all(promises).then(function(responses) {
responses.forEach(function(r, i) {
var imageObj = lcl_images[i],
element = document.getElementById(imageObj.id);
imageObj.value = URL.createObjectURL(r.blob());
if(element) { //safety
element.src = imageObj.value;
}
});
return responses; // here, return whatever you want to be made available to the caller.
}).catch(function(error) {
console.log(error);
});
If you prefer, you can write :
return Promise.all(values.reverse().map(fetch)).then(function(responses) {
// ...
});
2. Detail in .map()
followed a simple Promise.all()
var promises = values.reverse().map(function(val, i) {
return fetch(val).then(function(result) {
var imageObj = lcl_images[i],
element = document.getElementById(imageObj.id);
imageObj.value = URL.createObjectURL(result.blob());
if(element) { //safety
element.src = imageObj.value;
}
return result; // here, return whatever you want to be made available to the caller.
});
});
return Promise.all(promises).catch(function(error) { // return a promise to the caller
console.log(error);
});
Notes:
fetch()
fails.imageObj.value ...
and element.src = ...
stuff for all successful fetches even if one or more fetch()...
fails. Any single failure will cause Promise.all(promises)
to return a rejected promise..blob()
method returns a promise, not a value.You are returning from the then handler after first response, instead what you need to do is to return the list of blobs:
Promise
.all(promises)
.then(function(response) {
// CHANGED HERE
var blobPromises = [];
for (var i = response.length - 1; i >= 0; i--) {
blobPromises.push(response[i].blob());
}
return Promise.all(blobPromises);
})
.then(function(blob) {
console.log(blob.length);
for (var i = blob.length - 1; i >= 0; i--) {
lcl_images[i].value = URL.createObjectURL(blob[i]);
document.getElementById(lcl_images[i].id).src = objectURL;
}
})
.catch(function(error) {
console.log(error);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With