I understand this is a very common problem in RN and I am still trying to understand the very possible advantage of returning a promise when loading data from a property file instead of just returning the value, which makes chaining requests very cumbersome...but anyway. Here is what I have right now, which is a wrapper from the AsyncStorage RN implementation:
multiGet = async (key) => {
var value = null;
try {
value = await AsyncStorage.multiGet(key).then(
(values) => {
value = values;
console.log('Then: ',values);
});
} catch (error) {
console.log('Error: ',error);
}
console.log('Final: ',value);
return value;
}
At this point, value gets undefined. In my main code I have this:
var filter = this._getFilter();
console.log('returned filter:',filter);
The _getFilter function is the one using the AsyncStorage wrapper but the 'returned filter' is logging before the first function so it is not waiting for the returned values before continue, so I get an undefined value.
At first, I thought that just by using the async/await the AsyncStorage wold return a value instead of a promise but after testing, the value I get from:
value = await AsyncStorage.getItem('key')
is STILL a promise, so I have to use then() to read the value.
Basically the order that I am seeing in the logs is:
_getFilter
returned value: undefined
Then: value: here I get the correct value from the keys but the code already passed and I don't have the correct value in the variable
I have no clue what is going on or how to handle this correctly. This is supposed to be very simple and common use case.
I would love to solve this without using a third party module.
Thanks
SOLUTION Edit: After understanding a little more about the concepts of async/await and callbacks, I finally have a code that works. I don't like it, because it makes the code very hard to read. I might need to refactor it to use promises but for now, it works. Here are some snippets in case someone finds the same issue:
this._getFilter(body,this._filterSearchCallback,callback);
Note: I am sending the body through the chain because I am "completing" the information as I pass the functions. The second parameter is the first callback that actually makes a fetch query and the third callback is the return of the fetch function.
_getFilter(body,callback,returnCallback){
{...}
this._sh.multiGet(keysBanks).then(
(banks) => {
filter.banks = banks;
console.log(banks);
this._sh.multiGet(keysCards).then(
(cards) => {
console.log(cards);
filter.credit_cards = cards;
callback(body,filter,returnCallback);
});
}
);
}
Here basically I am chaining a couple of gets because I need several values from the store. This is the part I dont really like. _sh is my StorageHelper which is a wrapper to the AsyncStorage, nothing fancy.
multiGet = async (key) => {
const value = await AsyncStorage.multiGet(key);
return value;
}
Then my very last callback that actually makes the fetch and send the JSON response to the main screen in react native:
_filterSearchCallback(body,filter,callback){
body.filter = filter;
return fetch(apiUrl, {method: 'post', body: JSON.stringify(body)})
.then((response) => response.json())
.then((responseJson) => {
callback(responseJson);
})
.catch((error) => {
console.error(error);
callback(responseJson);
});
}
I will improve this and make it cleaner but for now, it works. Hope it helps others too.