Reputation: 121
I am attempting to clarify the issue previously stated. I've included the console logs to attempt to help track the flow through each function. Please my logical flow below:
Why are the IDs not resolving in the order that they were passed?
function getUserProfiles(){
//get users, usernames and render profiles
db.getUsers().then(users => {
console.log('first index:', users[0].id);
console.log('second index:', users[1].id);
console.log('third index:', users[2].id);
users.forEach(user => {
db.getLatestExperience(user.id).then(()=>{
})
})
}
Class {
getLatestExperience(id, callback) {
console.log('getLatestExperience before database request:', id);
return this.experience.where('userID', '==', id).orderBy('start','desc').get().then(snapshot => {
console.log('getLatestExperience promise resolved', id);
})
}
getUsers(callback) {
return this.users.orderBy('name').get().then(snapshot => {
return snapshot.docs;
})
}
}
first index: ZKnqtLVzUqNqdzX9f8ap76LThh32
second index: 482uR9t2QEdCUi0Z4nq14VRVhEx1
third index: 7bJBqk2gQBeTIZOY5h3FikO0Yqm2
getLatestExperience before database request: ZKnqtLVzUqNqdzX9f8ap76LThh32
getLatestExperience before database request: 482uR9t2QEdCUi0Z4nq14VRVhEx1
getLatestExperience before database request: 7bJBqk2gQBeTIZOY5h3FikO0Yqm2
getLatestExperience promise resolved: 482uR9t2QEdCUi0Z4nq14VRVhEx1
getLatestExperience promise resolved: ZKnqtLVzUqNqdzX9f8ap76LThh32
getLatestExperience promise resolved: 7bJBqk2gQBeTIZOY5h3FikO0Yqm2
*****ORIGINAL POST BELOW ********
I am working with firebase firestore. In my getUserProfiles() function, I call the getUsers function to return all of the userIDs in ascending order. Now, I take each one of these IDs and query the experience table by calling the getLatestExperience function. The problem is that the IDs are not being called in the correct order in my getLatestExperience function.
When I console log the IDs right after my getUsers function, they are in the correct order ( ZKnqtLVzUqNqdzX9f8ap76LThh32, 482uR9t2QEdCUi0Z4nq14VRVhEx1, 7bJBqk2gQBeTIZOY5h3FikO0Yqm2).
However, when i console log the IDs again inside the getLatestExperience function, they are in the wrong order ( 482uR9t2QEdCUi0Z4nq14VRVhEx1, ZKnqtLVzUqNqdzX9f8ap76LThh32, 7bJBqk2gQBeTIZOY5h3FikO0Yqm2).
In my getLatestExperience function, I noticed if I instead sort ascending instead of descending or remove the orderBy method altogether, it fixes the problem. But I need it to sort descending.
Please help me!
function getUserProfiles(){
//get users, usernames and render profiles
db.getUsers(user => {
let id = user.id;
let username = user.data().name;
console.log(id);
db.getLatestExperience(id, doc => {
//render profile template
})
})
}
Class Database{
getUsers(callback) {
this.users.orderBy('name').get().then(snapshot => {
snapshot.docs.forEach(doc =>{
callback(doc);
});
})
}
getLatestExperience(id, callback) {
this.experience.where('userID', '==', id).orderBy('start','desc').get().then(snapshot => {
console.log(id);
})
}
console log outs
app.js:135 ZKnqtLVzUqNqdzX9f8ap76LThh32
app.js:135 482uR9t2QEdCUi0Z4nq14VRVhEx1
app.js:135 7bJBqk2gQBeTIZOY5h3FikO0Yqm2
database.js:85 482uR9t2QEdCUi0Z4nq14VRVhEx1
database.js:85 ZKnqtLVzUqNqdzX9f8ap76LThh32
database.js:85 7bJBqk2gQBeTIZOY5h3FikO0Yqm2
Upvotes: 1
Views: 664
Reputation: 74046
Currently all requests to getLastExperience()
run in parallel. So the order in which they finish is more or less arbitrary. If you need (for whatever reason) to ensure the order or requests, you have to wait for one request to finish, before starting the next.
Something like the following could work (using async/await
):
Class Database{
async getUsers() {
const snapshot = await this.users.orderBy('name').get();
return snapshot.docs;
}
getLatestExperience(id) {
return this.experience.where('userID', '==', id).orderBy('start','desc').get();
}
}
async function getUserProfiles(){
//get users, usernames and render profiles
const users = await db.getUsers()
for( const user of users ) {
// get experience
const exp = await db.getLatestExperience( user.id );
// render
// ...
}
}
An alternative would be to first gather all information first and render afterwards. Trying to stick to your code so far, this could look like this:
async function getUserProfiles(){
//get users, usernames and render profiles
const users = await db.getUsers( async (user) => {
const id = user.id;
await db.getLatestExperience(id, (doc) => {
// augment user
user.exp = doc;
})
});
// render using users
// ...
}
Class Database{
async getUsers(callback) {
const snapshot = await this.users.orderBy('name').get();
return Promise.all( snapshot.docs.map( callback ) );
}
async getLatestExperience(id, callback) {
const exp = await this.experience.where('userID', '==', id).orderBy('start','desc').get();
return callback( exp );
}
}
Upvotes: 3