Reputation: 664
I am trying execute an asynchronous map over a list of image metadata objects.
For each object in the list, I check whether the string device_path
exists on the device. If it does not, I download the image to the device using RNFetchBlob & the object's parameter download_url
. After this I update the object's device_path
to the newly downloaded image.
When executing the code below, my function checkPaths
returns {"_40":0,"_65":0,"_55":null,"_72":null}
. I would like the function to return this:
[
{ device_path: 'goodimagepath1', download_url: 'mysecretdownloadurl1' },
{ device_path: 'goodimagepath2', download_url: 'mysecretdownloadurl2' }
];
How should I modify my function to work as intended?
import React, { Component } from "react";
import { View, Text } from "react-native";
import RNFetchBlob from "rn-fetch-blob";
async function checkPaths(image_metadata_list) {
const promises = image_metadata_list.map(async (image_metadata, idx) => {
RNFetchBlob.fs.exists(image_metadata.device_path).then(exists => {
if (exists === false) {
console.log("image does not exist on device, downloading...");
const dirs = RNFetchBlob.fs.dirs;
const filename = (idx + 1).toString() + '.jpg'
RNFetchBlob.config({
path: dirs.DocumentDir + `/user_images/${filename}`
}).fetch('GET', `${image_metadata.download_url}`).progress((received = 0, total = 0) => {
//Handle progress of download here.. May be update UI...\
}).then((resp) => {
// update the device path
image_metadata.device_path = resp.path();
console.log("image path modified", image_metadata);
return image_metadata;
}).catch(e => {
console.log("error downloading image", e);
})
}
else {
console.log("image path OK", image_metadata)
return image_metadata;
}
})
})
console.log("promises", promises)
results = await Promise.all(promises)
return results;
}
export default class App extends Component {
constructor(props) {
super(props);
this.image_references = [
{ device_path: 'badimagepath1', download_url:'mysecretdownloadurl1' },
{ device_path: 'badimagepath2', download_url: 'mysecretdownloadurl2' }
];
}
componentDidMount() {
console.log("component mounted");
console.log("checking image paths", JSON.stringify(this.image_references));
checked_paths = checkPaths(this.image_references);
console.log("checked image paths", JSON.stringify(checked_paths));
}
render() {
return (
<View style={{ flex: 1 }}>
<Text>Welcome to MWE</Text>
</View>
)
}
}
Upvotes: 1
Views: 1203
Reputation: 664
Since checkPaths is asynchronous, it returns a promise. This should be handled in componentDidMount
like so:
checkPaths(this.image_references).then(checked_paths => {
console.log("resolved promise", checked_paths)
console.log("checked image paths", JSON.stringify(checked_paths));
}).catch(e => {
console.log("error checking image paths", e)
});
I also modified the function checkPaths
to await checking for the image path & to await downloading the image.
If there is a cleaner way to do this i'm all ears.
import React, { Component } from "react";
import { View, Text } from "react-native";
import RNFetchBlob from "rn-fetch-blob";
async function checkPaths(image_metadata_list) {
const promises = image_metadata_list.map(async (image_metadata, idx) => {
const exists = await RNFetchBlob.fs.exists(image_metadata.device_path)
if (exists === false) {
console.log("image does not exist on device, downloading...");
const dirs = RNFetchBlob.fs.dirs;
const filename = (idx + 1).toString() + '.jpg'
const resp = await RNFetchBlob.config({
path: dirs.DocumentDir + `/user_images/${filename}`
}).fetch('GET', `${image_metadata.download_url}`).progress((received = 0, total = 0) => {
//Handle progress of download here.. May be update UI...\
}).then((resp) => {
// update the device path
image_metadata.device_path = resp.path();
console.log("image path modified", image_metadata);
}).catch(e => {
console.log("error downloading image", e);
})
}
else {
console.log("image path OK", image_metadata);
}
return image_metadata;
})
return await Promise.all(promises);
}
export default class App extends Component {
constructor(props) {
super(props);
this.image_references = [
{ device_path: 'badimagepath1', download_url: 'https://firebasestorage.googleapis.com/v0/b/fivedates-dev.appspot.com/o/user_images%2FoHK9DQ94ZZOBIejbVO8luJZnEU22%2F1.jpg?alt=media&token=6c5e053d-45b4-4ab0-a52b-65c1180624ed' },
{ device_path: 'badimagepath2', download_url: 'https://firebasestorage.googleapis.com/v0/b/fivedates-dev.appspot.com/o/user_images%2FoHK9DQ94ZZOBIejbVO8luJZnEU22%2F1.jpg?alt=media&token=6c5e053d-45b4-4ab0-a52b-65c1180624ed' }
];
}
componentDidMount() {
console.log("component mounted");
console.log("checking image paths", JSON.stringify(this.image_references));
checkPaths(this.image_references).then(checked_paths => {
console.log("resolved promise", checked_paths)
console.log("checked image paths", JSON.stringify(checked_paths));
}).catch(e => {
console.log("error checking image paths", e)
});
}
render() {
return (
<View style={{ flex: 1 }}>
<Text>Welcome to MWE</Text>
</View>
)
}
}
Upvotes: 1