So i'm fetching images from a remote server. then converting these images to base64 and pushing them to an empty array. the problem is the array length outside of that function doesn't get updated. i'm pretty sure it has to do something with the async/await function.
here's my code
const handleSubmit = async (listing) => {
const product = {files:[]};
const getBase64StringFromDataURL = (dataURL) => dataURL.replace('data:','').replace(/^. ,/, '');
for (let image of listing.images) {
await fetch(image)
.then((res) => res.blob())
.then((blob) => {
// Read the Blob as DataURL using the FileReader API
const reader = new FileReader();
reader.onloadend = () => {
const base64 = getBase64StringFromDataURL(reader.result);
product.files.push(base64)
// here the product.files length is updated without a problem
console.log(product.files.length)
};
reader.readAsDataURL(blob);
});
}
// here the length is 0
console.log(product.files.length)
}
please help figure this out. i'm open to a better alternative !
CodePudding user response:
fileReader.onload is asynchronous, I think console.log() is called before files have been read. You might want to make use of promise.all
& map
like this -
Promise.all([...listing.images].map(image => fetch(image)))
.then(resp => Promise.all(resp.map(file => new Promise((resolve, reject) => {
var blob = await file.blob();
var fileReader = new FileReader();
fileReader.onloadend = function readFile(e) {
const base64 = getBase64StringFromDataURL(reader.result);
resolve(base64);
};
reader.readAsDataURL(blob)
}))
.then(result => {
// get result array here
});
Use a promise
& map
instead of for
loop.
CodePudding user response:
if you are using await
, you don't need then
. instead you get result directly.
reader.onloadend
is asynchronous. so I suggest writing a wrapper function for it:
async function pushToArray(inputBlob, inputArray) {
return new Promise((resolve, reject)=>{
const reader = new FileReader();
reader.onloadend = () => {
/*logic...*/
inputArray.push(base64);
resolve(); // resolve should be here
};
reader.readAsDataURL(inputBlob);
});
}
// now your code be like:
let res = await fetch(image);
let blob = await res.blob(); // if res.blob() return a promise
await pushToArray(blob, product.files);
console.log(product.files.length); // 1