How to get PromiseValue with Promise {<pending>} Firebase? - javascript

Good afternoon. I'm new to working with Firebase batabase. Please tell me how to get data from my database to work with them farther.
Now my function returns Promise {} with the date that I need inside PromiseValue. How do I get it right.
Now my code looks like this
let firebaseConfig = {
....
};
firebase.initializeApp(firebaseConfig);
let ref = firebase.database().ref('/data')
function getDataPromise() {
return ref.once('value').then(function(snapshot) {
return snapshot.val();
});
}
let res = getDataPromise()
console.log(res)
I will be glad to any answer

You have to use then() to get the data,like below
let firebaseConfig = {
....
};
firebase.initializeApp(firebaseConfig);
let ref = firebase.database().ref('/data')
function getDataPromise() {
return ref.once('value').then(function(snapshot) {
return snapshot.val();
});
}
let res = getDataPromise()
// Use then() with a callback to get data
res.then(data => {
console.log(data)
})
console.log(res)

Related

How to get data from firestore to google cloud functions?

My index.js file:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const Firestore = require('#google-cloud/firestore');
const firestore = new Firestore();
admin.initializeApp();
const db = admin.firestore();
exports.getName = functions.https.onCall((data, context) => {
var docRef = db.collection("dogs").doc("{data.id}");
var getDoc = docRef.get().then(doc => {
return doc.get("name");
})
});
Code in the flutter project:
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable("getName");
var temp = await callable({"id": "11"});
print(temp.data);
The program prints out null, even though document in collection "dogs" with id "11" with a field name exists. I'm trying to get specific data from firestore and return it.
Console doesn't show any errors and if I'd return anything else it would print out normally.
Couldn't find any documentations about getting data from firestore to cloud function other than ones that use triggers like: onWrite.
Have you tried to make the cloud function async?
exports.getName = functions.https.onCall(async (data, context) => {
var doc = await db.collection("dogs").doc("{data.id}").get();
return doc.data().name;
});
andi2.2's answer is correct, but let me explain why it doesn't work with your initial code using then().
By doing:
exports.getName = functions.https.onCall((data, context) => {
var docRef = db.collection("dogs").doc("{data.id}");
var getDoc = docRef.get().then(doc => {
return doc.get("name");
})
});
You actually don't return doc.get("name"); in your Callable Cloud Function. The then() method does return Promise.resolve(doc.get("name")), as explained in the then() doc, but you don't return the Promise chain.
The following will work:
exports.getName = functions.https.onCall((data, context) => {
var docRef = db.collection("dogs").doc("{data.id}");
return docRef.get().then(doc => {
return doc.get("name");
})
});
BTW, are you sure that db.collection("dogs").doc("{data.id}"); is correct? Shouldn't it be db.collection("dogs").doc(data.id);?

Get one document from Firestore and return it to a variable

I have less experience with NodeJS, but I am trying to obtain one User document from Firestore.
const fs = firebase.firestore();
const usersRef = fs.collection('users');
let findUserByContact = (contact) => {
let res = usersRef.where('contact', '==', contact).get().then(querySnapshot => {
if (!querySnapshot.empty) {
return querySnapshot.docs[0].data();
} else {
return false;
}
});
};
I am trying to return the first document thats found. However that will always returns undefined when I am calling findUserByContact.
I could use console.log to see the output of my query. But I can't manage to assign it to a variable.
I've read into Promises, and I saw that it has to resolve something. I was trying to call resolve with the data I wanted to return but that gave me an error as wel.
You need to return the promise chain, as follows:
let findUserByContact = (contact) => {
return usersRef.where('contact', '==', contact).get()
.then(querySnapshot => {
if (!querySnapshot.empty) {
return querySnapshot.docs[0].data();
} else {
return false;
}
});
};
Note that the answer of #AkashDathan is also totally valid and the use of async/await makes it easier to read.
I would recommend that you use the async/await syntax
let findUserByContact = async (contact) => {
let querySnapshot = await usersRef.where('contact', '==', contact).get();
if (querySnapshot.empty) return false;
return querySnapshot.docs[0].data();
};

React.js, print something after all getDownloadURL functions completes

i am trying to get all the URL from Firebase.I need to print something after all the getDownloadURL completes. I have tried to add .then(function()){}after the storageRef.listAll(), however it does not work. Can someone help me? Thank you so much!
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
var that = this;
const storageRef = storage.ref(`image/${product}`)
storageRef.listAll().then(function(result) {
result.items.forEach(function(imageRef) {
imageRef.getDownloadURL().then(function(url) {
let a = 'a'
that.state.temp3.push(a)
console.log("789")
}).catch(function(error) {});
console.log("123")
})
console.log("456")
})
}
I declared a variable called promises and assigned all of the promises to it. After that, I used Promise.all to wait for all of the promises to resolve.
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
var that = this;
const storageRef = storage.ref(`image/${product}`);
storageRef.listAll().then(function(result) {
const promises = result.items.map(function(imageRef) {
return imageRef
.getDownloadURL()
.then(function(url) {
let a = "a";
that.state.temp3.push(a);
console.log("789");
})
.catch(function(error) {});
});
Promise.all(promises)
.then((results) => console.log('Promises resolved', results))
});
};

Using promises in Axios requests

I am trying to work out the best way to achieve something. When I land on a Profile page, the Profile component loads the data for that profile. This is assigned to this.profile. Within this data is a path to a file, where I want to process some data using this file. To me, the below approach seems slightly risky.
created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
axios.get(url).then(response => {
this.profile = response.data;
d3.json(response.data.fileName)
.then(function (data) {
//do some stuff
}).catch(function (error) {
// handle error
});
});
}
Instead of that, I want to ensure that I first have the data from the axios call. So I am thinking I need a promise? I was thinking something more along the lines off
created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
axios.get(url).then(response => {
this.profile = response.data;
}).then() {
d3.json(response.data.fileName)
.then(function (data) {
//do some stuff
}).catch(function (error) {
// handle error
});
};
}
But the above is incorrect, it is mainly to show what I am trying to achieve. I was wondering how I can maybe use deferred and promises to only execute the d3 stuff once the axios call is made.
Thanks
You can solve this by chaining promises, assuming that d3.json returns a promise:
created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
axios.get(url)
.then(response => {
this.profile = response.data
return d3.json(response.data.fileName)
}).then(data => {
//do some stuff
}).catch(err => {
//log error
})
}
That's where async/await comes in handy. A you don't need to save this to a variable and B you have cleaner, more readable code.
async created() {
const url = `/api/profile/${this.$route.params.id}`;
const { data } = await axios.get(url); // Optional destructuring for less clutter
this.profile = data;
const d3Data = await d3.json(data.fileName);
//do whatever you want
}
async created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
try {
const {data} = await axios.get(url)
const d3Data = await d3.json(data.fileName)
} catch(err) {
//error
}
}

First finish reading data from Firebase and then do something else

So my problem is that empty array is returned because reading data from Firebase is not finished yet. I am using then method but it still executes everything inside then before.
var usersList = [];
const ref = firebase.database().ref()
ref.child('users').once('value').then(snap => {
snap.forEach(childSnap => {
const key = childSnap.key
ref.child(`users/${key}/points`).on('value', function(snapper) {
var points = snapper.val()
usersList.push({uid: key, points: points})
})
})
}).then(function() {
console.log(usersList)
})
Using then() itself is not a magical solution. You need to return a promise from within the callback, which your code is not doing. In this case you only want the final then() to be invoked once all the users are loaded, so you need to return a promise that only resolves when done.
const ref = firebase.database().ref()
ref.child('users').once('value').then(snap => {
var promises = [];
snap.forEach(childSnap => {
const key = childSnap.key
promises.push(
ref.child(`users/${key}/points`).once('value')
);
});
return Promise.all(promises);
}).then(function(snapshots) {
return snapshots.map(snapper => {
var points = snapper.val()
return {uid: key, points: points};
})
}).then(function(usersList) {
console.log(usersList)
})

Categories