简体   繁体   中英

Asynchronous function console logging out of order

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:

  1. First i get the users with the getUserProfiles function.
  2. i confirm each user ID by printing out each index directly (users[0], users[1], users[2]).
  3. I then loop through each user and console log the user ID before and after the database query.
  4. Looking at the console logs, it looks like the user ids are being passed to the database query in the correct order, but the 2nd ID is resolving before the first ID. the first ID passed to the database is 'ZKnqtLVzUqNqdzX9f8ap76LThh32'. Yet, '482uR9t2QEdCUi0Z4nq14VRVhEx1' resolves first

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   

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 );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM