how to access json data os asyncStorage function - javascript

I am using AsyncStorage to store data. Here is my function of storing data :
const profile = { userId, name, email };
await AsyncStorage.setItem('userProf', JSON.stringify(profile));
I have a problem when I try to access the data , if I console.log:
async componentWillMount(){
const profile = await AsyncStorage.getItem('userProf');
console.log(profile);
}
{"userId":"jefla3E0tjcJHhHKJK45QoIinB2","name":"egfgege","email":"ergeg#egrge.com"}
Now if I am willing to get only email value , I have tried with:
console.log(profile.email);
console.log(profile[0].email);
None of them worked, I get undefined as output, could you please help.

As AsyncStorage take and returns a string you will need to parse the string into json. You're already using JSON.stringify to save your object, you need to do the reverse operation to get it back to being an object.
const savedProfile = await AsyncStorage.getItem('userProf');
const profile = JSON.parse(savedProfile);
Then you should be able to access it the properties as you normally would, for example
const userId = profile.userId;
const email = profile.email;
const name = profile.name;
You may want to make sure that you perform a check that the returned value from AsyncStorage isn't null, as that will cause problems for you. Also await functions can throw, so you should make sure that you wrap your call to AsyncStorage in a try/catch
async componentWillMount(){
try {
const savedProfile = await AsyncStorage.getItem('userProf');
// you should check that the savedProfile is not null here
const profile = JSON.parse(savedProfile);
const userId = profile.userId;
const email = profile.email;
const name = profile.name;
} catch (err) {
console.warn(err);
}
console.log(profile);
}

When storing the value with AsyncStorage.setItem( ... ), you use JSON.stringify to convert the complete object into a String. This means, if you want to have a "normal" Object back (to use the dot operator), you have to use JSON.parse:
const profile = await AsyncStorage.getItem('userProf');
console.log(JSON.parse(profile));

Related

Batch write with Firebase Cloud Functions

I'm using Firebase as backend to my iOS app and can't figure out how to construct a batch write through their Cloud Functions.
I have two collections in my Firestore, drinks and customers. Each new drink and each new customer is assigned a userId property that corresponds to the uid of the currently logged in user. This userId is used with a query to the Firestore to fetch only the drinks and customers connected to the logged in user, like so: Firestore.firestore().collection("customers").whereField("userId", isEqualTo: Auth.auth().currentUser.uid)
Users are able to log in anonymously and also subscribe while anonymous. The problem is if they log out there's no way to log back in to the same anonymous uid. The uid is also stored as an appUserID with the RevenueCat SDK so I can still access it, but since I can't log the user back in to their anonymous account using the uid the only way to help a user access their data in case of a restoring of purchases is to update the userId field of their data from the old uid to the new uid. This is where the need for a batch write comes in.
I'm relatively new to programming in general but I'm super fresh when it comes to Cloud Functions, JavaScript and Node.js. I dove around the web though and thought I found a solution where I make a callable Cloud Function and send both old and new userID with the data object, query the collections for documents with the old userID and update their userId fields to the new. Unfortunately it's not working and I can't figure out why.
Here's what my code looks like:
// Cloud Function
exports.transferData = functions.https.onCall((data, context) => {
const firestore = admin.firestore();
const customerQuery = firestore.collection('customers').where('userId', '==', `${data.oldUser}`);
const drinkQuery = firestore.collection('drinks').where('userId', '==', `${data.oldUser}`);
const customerSnapshot = customerQuery.get();
const drinkSnapshot = drinkQuery.get();
const batch = firestore.batch();
for (const documentSnapshot of customerSnapshot.docs) {
batch.update(documentSnapshot.ref, { 'userId': `${data.newUser}` });
};
for (const documentSnapshot of drinkSnapshot.docs) {
batch.update(documentSnapshot.ref, { 'userId': `${data.newUser}` });
};
return batch.commit();
});
// Call from app
func transferData(from oldUser: String, to newUser: String) {
let functions = Functions.functions()
functions.httpsCallable("transferData").call(["oldUser": oldUser, "newUser": newUser]) { _, error in
if let error = error as NSError? {
if error.domain == FunctionsErrorDomain {
let code = FunctionsErrorCode(rawValue: error.code)
let message = error.localizedDescription
let details = error.userInfo[FunctionsErrorDetailsKey]
print(code)
print(message)
print(details)
}
}
}
}
This is the error message from the Cloud Functions log:
Unhandled error TypeError: customerSnapshot.docs is not iterable
at /workspace/index.js:22:51
at fixedLen (/workspace/node_modules/firebase-functions/lib/providers/https.js:66:41)
at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:385:32
at processTicksAndRejections (internal/process/task_queues.js:95:5)
From what I understand customerSnapshot is something called a Promise which I'm guessing is why I can't iterate over it. By now I'm in way too deep for my sparse knowledge and don't know how to handle these Promises returned by the queries.
I guess I could just force users to create a login before they subscribe but that feels like a cowards way out now that I've come this far. I'd rather have both options available and make a decision instead of going down a forced path. Plus, I'll learn some more JavaScript if I figure this out!
Any and all help is greatly appreciated!
EDIT:
Solution:
// Cloud Function
exports.transferData = functions.https.onCall(async(data, context) => {
const firestore = admin.firestore();
const customerQuery = firestore.collection('customers').where('userId', '==', `${data.oldUser}`);
const drinkQuery = firestore.collection('drinks').where('userId', '==', `${data.oldUser}`);
const customerSnapshot = await customerQuery.get();
const drinkSnapshot = await drinkQuery.get();
const batch = firestore.batch();
for (const documentSnapshot of customerSnapshot.docs.concat(drinkSnapshot.docs)) {
batch.update(documentSnapshot.ref, { 'userId': `${data.newUser}` });
};
return batch.commit();
});
As you already guessed, the call customerQuery.get() returns a promise.
In order to understand what you need, you should first get familiar with the concept of promises here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
For your use case, you will probably end up with either using the then callback:
customerQuery.get().then((result) => {
// now you can access the result
}
or by making the method call synchronous, by using the await statement:
const result = await customerQuery.get()
// now you can access the result

retrieving data from database according to query conditions

"_id":{"$id":"61b5eb36029b48135465e766"},
"name":"push-ups","link":"https://google.com",
"image":"https://google.com",
"gender":["0","1","2"],
"goal":["lw","gw","sf"],
"age":60,
"excersietype":"chest",
"__v":0
this is how my data is stored in database
and I want to fetch data according to 3 condition
I got 3 queries from front gender goal and age and according to that I have to retrieve data
const gender = req.query.gender;
const age = req.query.age;
const goal = req.query.goal
const level = req.query.level
if (level==='fb'){
const getdata = new Forbeg.find({gender:{$in:gender}},{age:{$lte:age}},{goal:{$in:goal}});
console.log(getdata)
}
Is this a good way to find the data because I am getting error
UnhandledPromiseRejectionWarning: MongooseError: `Model.find()` cannot run without a model as `this`. Make sure you are not calling `new Model.find()`
I am getting above error while fetching
The error is explicit : Make sure you are not calling 'new Model.find()'. Use const getdata = Forbeg.find(...).
However, you will immediately run into the next problem, as Mongoose models return thenables (Promise-like). console.log(getdata) will log Promise<pending>. You need to resolve your database call, either by doing
Forbeg.find(...).then( getdata => console.log(getData));
or (much more better!):
const getdata = await Forbeg.find(...);
console.log(getdata)
Even better, add .lean() to get simple JSON data instead of an array of Mongoose objects (faster), and .exec() to get a true Promise instead of a thenable :
const getdata = await Forbeg.find(...).lean().exec();
console.log(getdata)
Remove new operator
const getData = Forbeg.find({gender:{$in:gender}},{age:{$lte:age}},{goal:{$in:goal}});

array destructuring mongoose create

is there any other way to insert a data into mongoose without using array desctructuring
i have some code below, it doesnt work, also it doesnt insert correctly into database
const data = req.file.originalname.split('.')[0].split('_');
if (data.length < 5) throw new Error('Invalid file name');
const content = await fs.readFile(req.file.path, 'utf8');
await orders.create({ data, content });
i can make this work by using this code by using array desctructuring like below, what i want to know is there any way without using desctructuring, and just using variable data like my code above
const data = req.file.originalname.split('.')[0].split('_');
if (data.length < 5) throw new Error('Invalid file name');
// const [no_telp, type, timespan, name, unique_code] = data;
const content = await fs.readFile(req.file.path, 'utf8');
await orders.create({ no_telp, type, timespan, name, unique code, content });
What you are doing is not array destructuring. Array destructuring means pulling data out of array. An example array destructuring could be const listCopy = [...list] or const listAdded = [...list, 12, 48]. If you mean this part create({ no_telp, type, timespan, name, unique code, content }); you are providing neessary data into create method. You can create an abject beforehand and just send pass it to create method. const userData = { no_telp, type, timespan, name, unique code, content }; await orders.create(userData);
Additionally, what you are trying to save is a stringified data. After reading a file with fs.readFile() you must parse it to manipulate and save in database correctly. Try this:
const stringData = await fs.readFile(req.file.path, 'utf8');
const content = JSON.parse(stringData)
console.log(content) // see the data
const userData = {no_telp, type, timespan, name, unique code, content};
await orders.create(userData);

Why am I getting an "undefined" result from my MongoDBQuery in Node?

I've already stablished a DB with it's schema like this:
When I use my search function in Nodejs it works perfectly and returns my info like this:\
So, why is is than when I try to fectch my user from mongodb and get the parameter "examenes":
I get this undefined return?:
The problem is you are not using await so in the line console.log(user.examenes) the variable user is not the data returned by mongo; is another object without attribute examenes. And trying to access the value is undefined.
So you can use:
let user = await (usuario.findOne({_id: req.params.id}))
Have you added mergeParams in your router?
This options adds params object to the request
const router = express.Router({ mergeParams: true });
then
/predict/:id results in req.params.id
By default this option is disabled in express
I think you should use the await keyword
try{
var user = await model.findOne({ _id: req.params.id});
} catch (e) {
// Handle Errors
};
Or
model.findOne({ _id: req.params.id}).then(result => {
var user = result;
}).catch(e=> {
// Handle Errors
});

Async Storage retrieve value of key in item

I'm new to Javascript and react native, and the question itself will be probably very easy to answer.
I'm setting up a AsyncStorage and creating a Item inside the storage, which is a .JSON that has 3 key values to it.
const saveDataToStorage = (token, userId, expirationDate) => {
AsyncStorage.setItem('userData', JSON.stringify({
token: token,
userId: userId,
expiryDate: expirationDate.toISOString()
}))
};
What I want to do now is to retrieve the "userId" value from this item in an other part of the project but here is the problem.
var PersonalId = await AsyncStorage.getItem('userData');
console.log(PersonalId);
console.log(typeof PersonalId);
I know how to access the item itself, but I have no clue how to access the special key inside it. I can not use the command:
var PersonalId = await AsyncStorage.getItem('userData').userId;
because the item from the AsyncStorage is a string, I know this because I got this info from the second line of my code.
console.log(typeof PersonalId);
How can I access the special key "userId" inside my item "userData" and not the whole item itself? I cant work with the item anyways because its a string, I can not treat it as an object and thats my problem.
Thank you for reading and helping out!
You need to first parse value you are getting from the AsyncStorage into a JSON object using JSON.parse(). Try this implementation.
const get_data = async () => {
const userData = await AsyncStorage.getItem("userData");
const userObject = userData !== null ? JSON.parse(userData) : {};
const personalId = userObject.userId;
console.log(personalId);
};
You are forgetting that you stringified the JSON before saving it to storage.. so you are getting string when you read it. Simply JSON.parse the returned string and you should be on your way.
const userData = await AsyncStorage.getItem('userData');
const personalId = JSON.parse(userData).userId;
You should also wrap the above code in a try-catch to make sure you catch errors when invalid data is tried to be parsed and it throws an error.

Categories