Reputation: 23
I'm tryin to achieve a function which will return all rooms of specific user. I'm working with firebase
and to get a specific room I wrote this function:
Db.prototype.getRoom = function (roomUid){
return new Promise(function(resolve, reject) {
firebase.database().ref('rooms/' + roomUid).once('value').then(function(snapshot){
resolve(snapshot.val());
})
});
}
Here is my problem - I need to download all rooms before returning the array. I've tried:
Db.prototype.getUserRooms = function(user){
var rooms = [];
firebase.database().ref('users/' + user.uid + '/rooms')
.once('value').then(function(snapshot){
var roomsIds = snapshot.val() || []; //array of rooms ids
for(var i = 0; i < roomsIds.length; i++){
Db.prototype.getRoom(roomsIds[i]).then(function(room){
rooms.push(room);
});
}
return rooms;
});
}
Thanks for any help
Upvotes: 2
Views: 74
Reputation: 707218
You have to do a couple things to make this work.
First, when you use a for
loop to retrieve a bunch of async values, you have to collect all the promises and use Promise.all()
to wait for all those async operations to be done.
Second, when you have a promise inside of a .then()
handler, you need to return that promise from the .then()
handler to chain it together.
Third, when you want to call a method from within another method, you need to call it on the instance of your object, not directly on the prototype.
// return the inner promise directly rather than wrap in a new promse
Db.prototype.getRoom = function (roomUid){
return firebase.database().ref('rooms/' + roomUid).once('value').then(function(snapshot){
// make the `.val()` result be the fulfilled value of the promise
return snapshot.val();
})
});
}
Db.prototype.getUserRooms = function(user){
var self = this;
return firebase.database().ref('users/' + user.uid + '/rooms').once('value').then(function(snapshot){
var roomsIds = snapshot.val() || []; //array of rooms ids
return Promise.all(roomsIds.map(function(roomID) {
return self.getRoom(roomID);
}));
});
}
Them, I'm still a bit confused why you're calling methods directly on the prototype such as Db.prototype.getRoom()
. Usually, when using object oriented Javascript, you would call methods on an instance of the db
object, not directly on the prototype. I've modified getUserRooms()
to work this way, calling .getRoom()
on the instance.
Then, usage would be like this:
// assumes mydb is an instance of your Db object
mydb.getUserRooms(someUser).then(function(rooms) {
// rooms is an array of rooms
console.log(rooms);
});
Upvotes: 2