Асинхронная функция консоли выходит из строя - PullRequest
0 голосов
/ 22 мая 2019

Я пытаюсь прояснить ранее заявленную проблему. Я включил журналы консоли, чтобы попытаться отследить поток через каждую функцию. Пожалуйста, мой логический поток ниже:

  1. Сначала я получаю пользователей с помощью функции getUserProfiles.
  2. я подтверждаю каждый идентификатор пользователя, распечатывая каждый индекс напрямую (пользователи [0], пользователи [1], пользователи [2]).
  3. Затем я перебираю каждого пользователя и записываю в журнал идентификатор пользователя до и после запроса к базе данных.
  4. Глядя на журналы консоли, похоже, что идентификаторы пользователя передаются в запрос к базе данных в правильном порядке, но второй идентификатор разрешается до первого идентификатора. первым идентификатором, переданным в базу данных, является 'ZKnqtLVzUqNqdzX9f8ap76LThh32'. Тем не менее, '482uR9t2QEdCUi0Z4nq14VRVhEx1' разрешается первым

Почему идентификаторы не разрешаются в том порядке, в котором они были переданы?

    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

***** ОРИГИНАЛЬНЫЙ ПОЧТ НИЖЕ ********

Я работаю с пожарным магазином. В моей функции getUserProfiles () я вызываю функцию getUsers, чтобы вернуть все идентификаторы пользователя в порядке возрастания. Теперь я беру каждый из этих идентификаторов и запрашиваю таблицу опыта, вызывая функцию getLatestExperience. Проблема в том, что идентификаторы не вызываются в правильном порядке в моей функции getLatestExperience.

Когда я консоль регистрирую идентификаторы сразу после моей функции getUsers, они находятся в правильном порядке (ZKnqtLVzUqNqdzX9f8ap76LThh32, 482uR9t2QEdCUi0Z4nq14VRVhEx1, 7bJBqk2gQBeTIZOY5Ym2O).

Однако, когда я снова регистрирую идентификаторы внутри функции getLatestExperience, они находятся в неправильном порядке (482uR9t2QEdCUi0Z4nq14VRVhEx1, ZKnqtLVzUqNqdzX9f8ap76LThh32, 7bJBqk2gQBh2O5).

В моей функции getLatestExperience я заметил, что если вместо сортировки по возрастанию вместо сортировки убрать или убрать метод orderBy, это устранит проблему. Но мне нужно это сортировать по убыванию.

Пожалуйста, помогите мне!

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

выход из консоли

    app.js:135       ZKnqtLVzUqNqdzX9f8ap76LThh32
    app.js:135       482uR9t2QEdCUi0Z4nq14VRVhEx1
    app.js:135       7bJBqk2gQBeTIZOY5h3FikO0Yqm2
    database.js:85   482uR9t2QEdCUi0Z4nq14VRVhEx1
    database.js:85   ZKnqtLVzUqNqdzX9f8ap76LThh32
    database.js:85   7bJBqk2gQBeTIZOY5h3FikO0Yqm2   

1 Ответ

2 голосов
/ 22 мая 2019

В настоящее время все запросы к getLastExperience() выполняются параллельно. Так что порядок, в котором они заканчиваются, более или менее произвольный. Если вам необходимо (по какой-либо причине) обеспечить заказ или запросы, вам нужно дождаться завершения одного запроса, прежде чем начинать следующий.

Может работать что-то вроде следующего (используя 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
    // ...
  }
}

Альтернативой было бы сначала собрать всю информацию сначала, а потом обработать. Попытка придерживаться вашего кода до сих пор, это может выглядеть так:

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