Getting empty snapshot when reading Firebase Database in Javascript? - javascript

I have the following database structure:
I am trying to get the list of values under registrationTokens to then execute an FCM notification to the list of tokens. But the output to the console is empty even though there is a token under the child node. Am I missing something here?
Console output:
registrationTokens [ '0' ]
Part of my JS function code below:
return admin.database().ref('/fcmtokens/' + toId + '/registrationTokens').once('value').then((userTok) => {
const registrationTokens = Object.keys(userTok.val());
console.log('registrationTokens', registrationTokens);
});

Your console output is exactly as I'd expect. You've read the following children from the database:
0: 'c4P...'
Then you asked for the keys of that object to be printed, as returned by Object.keys(). Note that this key a key/value pair: the key is 0 and the value is 'c4P...'. This means that the following call:
Object.keys(userTok.val());
Is going to return an array of keys of the children. Since there is one child with a key of 0, you get this array:
[ '0' ]
So, I'd say your function is working exactly as you coded it. If you want the token values instead, try this:
If you want to tokens for each key instead, maybe you should use Object.values() instead:
Object.values(userTok.val());
I'd expect that to return an array of all the values associated with they keys.

Related

React Native Expo with Firebase: DataSnapshot is object not array

I have some simple data that looks like this, stored in a realtime database of firestore by calling update() and adding in an array as paremeter.
The game is generated by creating an array here and setting it in the "participants" field:
generateNewGame(code, name) {
this.database.ref().update({
[code]: { participants: [name] },
});
}
Now it is time to read the data, this is done by this method setting up a listener:
function setupRegisteredUsersListener() {
FirebaseService.getDatabaseReference(
"/" + codeRef.current + "/participants"
).on("value", (snapshot) => {
if (snapshot.val()) {
// setUsers(snapshot.val());
console.log(typeof snapshot.val());
console.log(JSON.stringify(snapshot.val(), null, 4));
}
});
}
Even though I stored the data as an array, and it LOOKS like an array, the type is Object. How can I circumvent this behaviour, or do I have to manually convert the object to an array somehow?
The documentation, says the .val() function should be able to convert the DataSnapshot into an array. But apparently that is not the default in my case.
The output from the function looks like this:
So obviously the daya is ALMOST an array, but not quite.
Do I have to manually convert the object to an array somehow?
No, you can directly use the value returned by snapshot.val() as an Array.
Array.isArray(snapshot.val()) will return true.
Also, for example, the following will return 0
console.log(snapshot.val().findIndex((element) => element === 'Hej'));
Or, if you add another element, the following will print the values of the two elements
console.log(snapshot.val()[0]);
console.log(snapshot.val()[1]);

Can't access data in array after mapping it from api pull

So I have pulled some data from an api using a fetch in a React app, then I have used .map to get the data I want into arrays that I am trying to present in a table sort of format.
When I log the mapped arrays it presents the data I am after, but when I try access it to present specific elements of it it's returning undefined.
If the array in the console log shows that it has elements name and age, is there something I am doing wrong to get undefined when I try and access it? Or maybe I am accessing it the wrong way. Any help would be appreciated.
function getMap(results) {
return results.map((res) => {
return {name: res.name, age: res.age}
}
fetch(URL)
.then(result) {
let x = getMap(result.result);
console.log(x);
///// the console log shows an array [{name: 'Peter', age: 30}]
console.log(x.name);
///// console log returns undefined
})
you aren't accessing the array correctly. Remember an array is like a "list" of things, in this case, objects. Each object has two properties, name and age. The way you are trying to access it in your second console.log, you are trying to access a .name property on the array itself. This is pretty basic, but to access an item in an array, you pass an index (starting at zero), like so: myArray[0]. So to access the name property of the first item in your array, you would use x[0].name. To iterate over the entire array, you could do x.forEach(item => console.log(item.name))

Javascript string/object/array confusion with JSON

I'm having a Laravel backend return some errors via Validator. These errors are passed through a HTTP response made by angular, and returned in JSON format.
The object is structured as seen below:
That name object has a value, which is the actual message that I'm after.
Currently, using loops etc., I can only get the name of the array (name) as a string...
I sometimes get multiple arrays within this error object, and I won't always know their names, so how may I retrieve that 0-index value in each of them, in a loop?
Thanks for any help.
Edit #1
Looping through it like this:
for(var err in res.data.errors){
console.log(Object.err[0][0]);
}
Gives me a Cannot get [0] index of undefined
How about this:
let errors = Object.values(response.data.errors);
// errors is now an array of arrays containing the validation errors
errors.forEach( (errorArray) => {
console.log(errorArray[0]);
} );
Another approach would be using Object.keys() instead of values. This is similar to what you already tried, where you get the name of the error property as a string, and then use it to access each error array:
let keys = Object.keys(response.data.errors);
keys.forEach( (errorKey) => {
console.log('error type', errorKey);
let errorArray = response.data.errors[errorKey];
console.log(errorArray[0]);
} );

How To Efficiently Extract Certain Information From A POJO

I am working a lot with firebase, and am trying to load certain information from the database. The original data comes from a query, and is returned to me in a POJO. The console prints this when the original data is returned:
-KhQ76OEK_848CkIFhAq: "-JhQ76OEK_848CkIFhAq"
-OhQ76OEK_848CkIFhAq: "-LhQ76OEK_848CkIFhAq"
What I need to do is grab each of the values (-JhQ76OEK_848CkIFhAq and -LhQ76OEK_848CkIFhAq) separately, and query the real-time database again for each one. I can manage that aspect, but I cannot seem to figure out how to separate the values.
I have already tried to get a single output by doing:
console.log(vals[0]) but it just returned undefined, and splitting the string by " would be very inefficient for large data sets. Any ideas?
To access the values, you can iterate the snapshot's children using the snapshot's forEach method. The keys and values of the children can be obtained using the key property and the val() method:
firebase.database()
.ref("some/path")
.once("value")
.then((snapshot) => {
snapshot.forEach((childSnapshot) => {
console.log(childSnapshot.key); // The child's key: e.g. "-KhQ76OEK_848CkIFhAq"
console.log(childSnapshot.val()); // The child's value: e.g. "-JhQ76OEK_848CkIFhAq"
});
});
To solve this issue, all I did was convert the object returned into an array by using this code below:
var Array = Object.keys(datalist).map(function(k) { return datalist[k] });
Works like a charm, and I can now run a simple for loop for Array

Array containing objects has wrong length

I have an array like:
errors = [ {...}, {...}, {...} ]
It's an instanceof array, yet it only returns 1 for .length?
Relevant code:
if(data.error){
errors.push({'element':ele,error:data.error});
}
//Above is looped a few times and there are N number of errors now inside
console.log(errors) //Returns 2+ objects like {...}, {...}
console.log(errors.length) //Returns 1
For Uzi and Muirbot, here's the errors array:
[
Object
element: b.fn.b.init[1]
error: "You must enter "example" into the field to pass"
__proto__: Object
,
Object
element: b.fn.b.init[1]
error: "Crap!"
__proto__: Object
It is correct, this code:
var errors = new Array();
errors.push({'element':'ele', error:'data.error'});
...adds ONE object to the array. The object has two properties.
It's possible your code is executing in an order other than what you're expecting. ie, when you log both errors and errors.length, errors does contain only 1 object. But after that you are adding to the errors array, and only after that are you looking at the console. At that point you could see a larger array in errors for two reasons - first, your actual code isn't logging errors but some object that contains errors. In that case the console display is live, and will show you not what was in errors at the time, but what is in it now. Alternatively, the console could just be taking some time to log errors.
Without more code I can't be sure if this is the case. But you could verify it by replacing console.log(errors); with console.log(errors[1]);. If errors is really only 1 long at the time, it will log undefined.
The problem was that Chrome's Web Inspector's console.log is an async event. So, the length was a property lookup so it gave that back instantly, but the object with two items inside was held off until the rest of the events had fired.
In the future I, and others with this issue, should use debugger; instead.
is it an Array object or something that resembles it?
arrays do work:
> a = [{a:1}, {b:2}]
[Object, Object]
> a.length
2
you'll have to provide more code.
and now that you've provided the relevant code, the correct answer is what Steve Wellens said (which was downvoted, by the way).
Array.push adds a single element, objects may have more than one key but they're still a single object so your real case was different from your original example, which of course works.
another possibility:
> a = []
[]
> a.length = 2
2
> a
[]
> a.length
2
> a instanceof Array
true

Categories

Resources