I am Using promise to get dimensions of multi uploaded image files. This is what I tried but I got empty array.
<input type="file" multiple>
Javascript file
$('input').change(function() {
var filereaders = [];
var dimensions = [];
for (var i = 0; i < this.files.length; ++i) {
filereaders[i] = new FileReader;
filereaders[i].onload = function() {
var img = new Image;
dimensions[i] = new Promise(function (resolve, reject) {
img.onload = function() {
resolve(img.width)
};
})
img.src = this.result;
}
filereaders[i].readAsDataURL(this.files[i]);
}
Promise.all(filereaders).then(function(res){
Promise.all(dimensions).then(function(dims){
console.log(dims) // [] array,I expect [23,434,123]...
}).catch(function(errdims){
console.log(errdims)
})
}).catch(function(err){
console.log(err)
})
});
Promise.all(filereaders)
filereaders
is an array of FileReader instances, not an array of Promises. Calling Promise.all
on this array will immediately resolve the Promise, before any fileReader.onload
event handlers have fired. Therefore, the dimensions
array is still empty at this point. Now we get to Promise.all(dimensions)
, and it's an empty array.
For your first Promise.all
call, you could wrap your FileReaders in Promises and resolve them onload
:
var filereaders = []
for (var i = 0; i < this.files.length; ++i) {
var file = this.files[i]
filereaders.push(new Promise(function (resolve, reject) {
var fileReader = new FileReader;
fileReader.onload = function() {
var img = new Image;
dimensions[i] = new Promise(function (resolve, reject) {
img.onload = function() {
resolve(img.width)
};
})
img.src = this.result;
resolve();
}
fileReader.readAsDataURL(file);
}))
}
Now, filereaders
is an array of Promises, so you can use Promise.all
on it.
There are some other things that could be done to simplify this code, though. File
objects in JavaScript are Blob
s, and Blobs can be added as Image .src
s without first reading them with a FileReader. Use URL.createObjectURL:
var dimensions = [];
for (var i = 0; i < this.files.length; ++i) {
var file = this.files[i];
dimensions.push(new Promise(function (resolve, reject) {
var src = URL.createObjectURL(file);
var img = new Image;
img.onload = function () {
resolve(img.width);
URL.revokeObjectURL(src);
};
img.src = src;
}));
}
Now we only need to wait for Promise.all(dimensions)
, and we can forget about filereaders
entirely.
Promise.all(dimensions).then(function(dims){
console.log(dims) // [] array,I expect [23,434,123]...
}).catch(function(errdims){
console.log(errdims)
})