Getting actual value from react-native asyncStorage instead of promise - javascript

All morning I've been trying to get the AsyncStorage.getItem to return the value of the actual item, not a promise.
Here's what I have that according to everything I've read should work:
export async function getToken(){
try{
var value = await AsyncStorage.getItem('authToken');
return value;
}catch (error){
console.log(error);
}
}
I have tried chaining together many .thens, tried accessing the actual value field of the promise, but for some reason that returns a promise also. I've tried pretty much every suggestion on this site and it will always return a promise.

Quoting the AsyncStorage documentation
... Each method in the API returns a Promise object.
and also based on this post, there is no way for you to access the value without the use of promise or any other async patterns (generators, callback etc).
You can use Realm as a storage without using promises. This is how you query data in realm (quoting the documentation):
let token = realm.objects('authToken'); // retrieves all authTokens

Related

Firebase .update() returning undefined, is it not supposed to return the updated object?

I have a simple update Firebase function, which looks like the following:
export default async function updateStuff(firestore, id, data) {
const stuff = await firestore
.collection('Stuff')
.doc(id)
.update(data)
console.log('updated stuff:', stuff) // Will always be undefined, despite working.
}
The update is working as expected and everything, however, once the Promise goes through all I have is undefined. I could have sworn that it once returned the actual entry that was updated with its updated values, does it not do so anymore?
Is there something that could be done to verify that it has been in fact updating without doing a whole separate .get() call after the update?
I can't find the proper update() API docs, but I did as stated on this page:
To know when your data is committed to the Firebase Realtime Database server, you can use a Promise. Both set() and update() can return a Promise you can use to know when the write is committed to the database.
Is it just a Promise<void> with no other information on the updated object? And I can assume it will throw if it fails? I just seems counter-productive for an update API to have to keep refetching values once the operation is done.
If you look at the reference documentation for DocumentReference.update(), you'll see that it returns Promise<void>.
If you need the updated data, you'll need to get() that in a separate call. If you update multiple documents, you may need multiple get() calls too.
The promise will indeed be rejected when the operation fails.

How to get value from db.any() promise in pg-promise?

I use pg-promise and i tried to make a request to database in user model to get an array of all users like this:
exports.getAllUsers = function () {
let users = db.any("SELECT * FROM users;").then(function (data) {
return data; // in debug mode data is my expected array
});
return users;
};
But when i make get request from controller, it returns promise Promise { <pending> }, not an array of json objects that I expected.
There is a controller:
exports.getUsers = function (req, res) {
let users = userModel.getAllUsers();
console.log(users); // here it outputs Promise { <pending> }
res.json(users);
};
How to get array instead of promise?
Let's break down your code. You are exporting a function of your design, getUsers, which is supposed to return a sequence of user objects. But it does not -- db.any(...) returns a Promise. How else do you think you can call then on the returned object? then is a member function of the Promise class, and you pass another function to then to work with the actual data (passed as parameter to the function you pass to then). Meaning that indeed data, as passed to the then call invoked on the return value of db.any(...) call, is the sequence of users you're after.
The mistake you are making is to assume that if you return data from the callback passed to then, it will become the return value of the then(...) call. It will not. then always returns a Promise -- whatever you return from the callback to then will become the resolved value of the returned promise, but it is the promise that is returned and that is why your users variable is a Promise.
You need to read more about promises, and how they are resolved asynchronously (between running your scripts), and how to synchronise your code on them resolving.
Hint: Use the await keyword to wait for and use the value given a promise, like the value you return from the callback that you pass to your then(...) call, or accept the design of your getUsers function returning a promise and adapt the rest of your code to work with that, without use of await.
Your getAllUsers function can be reduced to:
exports.getAllUsers = function () {
return db.any("SELECT * FROM users;");
}
...and with await you can then use it like:
let users = await getUsers();
The statement above has to be part of a function that is tagged as async though -- ECMAScript requires marking these explicitly in order to allow use of await expressions:
async function whatever() {
let users = await getUsers();
/// ...
}
Execution of a script that invokes an async function such as one containing the statement above, will be interrupted by the JavaScript interpreter at each await expression, and resumed when the promise expressed after the await keyword, resolves to a value, with the value being assigned to the users variable.
Using async and await does require a version of Node.js that can support them, but current release does (as of the time of writing this).
Otherwise you can still keep the getUsers function, but you need to use it differently since you can't use await -- having to use promises as one did prior to introduction of await and async, like:
getUsers().then(users => {
/// Do something with the `users` array.
});
At any rate, it looks like you have some holes in your understanding of how promises work, and I recommend you fill these holes by reading about them this time and not just going straight through to the pg-promise API, which builds on them.
Like you already found out userModel.getAllUsers() will return a promise and not an array. You need to wait for this promise to be resolved. This can be done using the an async function.
exports.getUsers = async function (req, res) {
let users = await userModel.getAllUsers();
console.log(users);
res.json(users);
};
Note that an async function will always return a promise.
Or you can make use of then method of the returned promise.
exports.getUsers = function (req, res) {
userModel.getAllUsers().then(users => {
console.log(users);
res.json(users);
});
};

How do I wait for a value to be retrieved from API calls. Before starting my code

Supposed I have a json object from a url.
fetch(URL, setting)
.then(loadRes)
.then(logger)
function loadRes (res){
return res.json();
}
Not sure whether async is needed right below.
async function logger (reply){
let stringReply = await reply.answer;
console.log("Obtain value " + stringReply) //let the value be a string e.g "apple"
sendingReply(stringReply);
return stringReply
}
Using express
app.post('/', function( req, res){
console.log(sendingReply())
}
when i tried logging the results again, it shows promise { <pending> }
So how can I retrieved the value from the earlier on. Waiting for the value to be retrieved
Correct me if I'm wrong, my understanding is that when the code is being run, it execute everything at once. So therefore by the time I received a result from the URL link (json object), it is already done executing it.
If you are sure that reply.answer is a resolved promise, then only await would be required. Since you've mentioned it is returning Promise { <pending> }, I guess it would be an unresolved Promise which gives a pending state.
x=new Promise((resolve,reject)=>("vre")) //gives PromiseĀ {<pending>}
x=new Promise((resolve,reject)=>resolve("vre")) //gives PromiseĀ {<resolved>: "vre"}
I hope that resolves your concern.
If you're using await then async function is required and in this case correctly used. However, await has to be used before a promise call.
What does reply.answer return? if it returns a promise then reply.answer() is the correct way to call that function.
Please let know your output error message, also let me know what's the purpose on sendingReply(), it's supposed to return a promise? does it return a value?

Correct way to return a promise from firebase's onCall function?

According to the docs I've read, an onCall function should return a promise. Something like this:
...onCall((data, context) => {
return db.collection('game').doc(game_id).delete();
});
...
This simply takes the promise associated with the delete function and returns it to the caller.
However, if I want to take an additional step after delete, then there are multiple return paths and I'm not clear on what to return:
...onCall((data, context) => {
return db.collection('game').doc(game_id).delete()
.then(){
return db.collection('user').doc(user_id).delete()
}
//.catch(){ return ??? }
});
...
I've seen code similar to what I've typed above, but it isn't clear to me that this is correct.
First, is it saying that by returning the game deletion promise, if there is an error, it will be returned to the user and if it is successful, then the user deletion promise will be returned to the user? What if there is a user deletion exception?
Do I have to create my own Promise object and call resolve or reject myself?
It's fine the way it is. You almost never need to create a new Promise. That's for cases where you call a function that doesn't return a promise, and provides a callback instead.
There are a lot of resources out there on learning to deal with promises. It doesn't really matter if the code is running in Cloud Functions or not - JavaScript promises work the same in any context. A callable function just needs that promise to know when the work is complete, and what to return to the caller.
...onCall((data, context) => {
return db.collection('game').doc(game_id).delete()
.then(){
return db.collection('user').doc(user_id).delete()
}
//.catch(){ return ??? } });
I've seen code similar to what I've typed above, but it isn't clear to
me that this is correct. First, is it saying that by returning the
game deletion promise, if there is an error, it will be returned to
the user and if it is successful, then the user deletion promise will
be returned to the user? What if there is a user deletion exception?
What you have in this code is Promise chaining, with the then() method. Since a call to promise.then() returns a Promise, the first return does return a promise and therefore it is fine for the Callable Cloud Function.
However, to answer to the end of your question, you should note that:
If there is an error in the game deletion, the CF will stop and neither the game nor the user will be deleted
If there is an error in the user deletion, the CF will stop and the game will be deleted (successfully deleted before the error) but not the user.
If you want to be sure both are deleted in one atomic operation (both are deleted or none is deleted), you should use a batched write as follows:
...onCall((data, context) => {
let batch = db.batch();
const gRef = db.collection('game').doc(game_id);
batch.delete(gRef);
const uRef = db.collection('user').doc(user_id);
batch.delete(uRef);
return batch.commit()
});

Await returns [Function] instead of value

await returns [Function] instead of value
Trying to return the values of a query from firebase by making use of the async and await function. Results returned are either [Function] or Unhandled Promise Rejection Warnings. New to promises, async and await but I've tried the basic examples on a few websites, most having the resolve and reject parameters, which I assume should be the same as the firebase promises.
I tried 2 different version, both with incorrect results.
get_all_users:async function(){
ref = db.ref("/user_data");
const value = await ref.orderByKey().on("child_added", function(data){});
console.log(value.val().name);
}
returns UnhandledPromiseRejectionWarning
function get_async_users(){
ref = db.ref("/user_data");
ref.orderByKey().on("child_added", function(data) {
return data.val().name;
});
}
returns undefined
Expected either one to return the names from the query.
on is for listening to all events that ever get triggered. Therefore it does not return a Promise, as a Promise represents a single value being available, and as it does not return a Promise, you can't await it (or at least: it doesn't make sense to do so, its a no-op).
If you want to wait for the first occurence, there is once, which also returns a promise that can be awaited.
Concerning the UnhandledPromiseRejection: You should always wrap your asynchronous code into a try / catch (inside an async function), or attach a .catch to the upmost promise in the chain, then you can handle those errors correctly.

Categories

Resources