承诺没有按照被称为的顺序解决

时间:2019-05-23 06:23:18

标签: javascript firebase asynchronous promise

我正在将一个网站与Firebase集成在一起。我试图从数据库中的用户集合中获取用户ID,然后将每个用户ID传递给另一个函数,该函数从另一个集合中获取体验数据。我按名称对用户排序,因为我希望用户在页面上按字母顺序排序。该代码按我的方式工作,只是承诺没有按照正确的顺序解析,因此不会按字母顺序输出。请在下面查看详细信息:

  1. 首先,我使用getUserProfiles函数获取用户。
  2. 我通过直接打印出每个索引(用户[0],用户[1],用户[2])来确认每个用户ID。
  3. 然后我遍历每个用户,并在数据库查询之前和之后通过控制台记录用户ID。
  4. 查看控制台日志,看起来用户ID已按照正确的顺序传递给数据库查询,但是第二个ID在第一个ID之前正在解析。传递给数据库的第一个ID是“ ZKnqtLVzUqNqdzX9f8ap76LThh32”。但是,'482uR9t2QEdCUi0Z4nq14VRVhEx1'首先解析

为什么ID不能按传递顺序解析?

    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

2 个答案:

答案 0 :(得分:0)

您可以将承诺放在一个数组中,然后reduce将它们按顺序执行:

const promiseArray = [promise2, promise3...]
    promiseArray.reduce(
        (prev, next) => prev.then(prevResult => next(prevResult)), promise1())
            .then(finalResult => {...})

promiseArray是一个返回承诺的函数数组。您省去了第一个,因为以后需要一个开始。 Array.reduce将一个接一个地执行。 prev是您正在解决的先前承诺,如果需要,对于下一个承诺,您可以将其解决并得到结果,然后将其传递给下一个。 最终,您可以从最后的承诺中得到一个结果,即可解决整个缩减问题。

答案 1 :(得分:0)

您可以使用Promise.all来解决所有用户返回时的问题。 Promise.all内置了该命令,以使结果数组与给定的Promise相同

function getUserProfiles() {
  //get users, usernames and render profiles
  return 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);

      const latestExperiencePerUserPromises = users
        .map((user) => db.getLatestExperience(user.id));

      return Promise.all(latestExperiencePerUserPromises);
    });
}