【问题标题】:Waiting for all firebase call to finish with map function等待所有 firebase 调用使用 map 函数完成
【发布时间】:2019-06-28 16:25:59
【问题描述】:

我正在获取我的用户数据,并且每个用户都会多次调用 map 函数。我想等到所有数据都被推送到数组中,然后再操作数据。我尝试使用 Promise.all() 但它没有用。 在继续之前如何等待此地图功能完成?

不用说,当在 Promise.all() 中打印时,数组 user_list_temp 是空的。

 const phone_list_promise_1 = await arrWithKeys.map(async (users,i) => {
      return firebase.database().ref(`/users/${users}`)
          .on('value', snapshot => {
              user_list_temp.push(snapshot.val());
              console.log(snapshot.val());
            })
        }
  );

Promise.all(phone_list_promise_1).then( () => console.log(user_list_temp) )

我把代码改成了这个,但我仍然得到一个错误的输出

Promise.all(arrWithKeys.map(async (users,i) => {
      const eventRef = db.ref(`users/${users}`);
      await eventRef.on('value', snapshot => {
        const value = snapshot.val();
        console.log(value);
        phone_user_list[0][users].name = value.name;
        phone_user_list[0][users].photo = value.photo;
      })
      console.log(phone_user_list[0]); 
      user_list_temp.push(phone_user_list[0]);
    }

  ));
    console.log(user_list_temp); //empty  array
}

【问题讨论】:

    标签: javascript firebase react-native firebase-realtime-database


    【解决方案1】:

    如果我正确理解您的问题,您可能会考虑修改您的代码以使用常规的 for..of 循环,每个用户都有一个嵌套承诺,当该用户的快照/值可用时解析:

    const user_list_temp = [];
    
    /*
    Use regular for..of loop to iterate values
    */
    for(const user of arrWithKeys) {
    
        /*
        Use await on a new promise object for this user that
        resolves with snapshot value when value recieved for
        user
        */
        const user_list_item = await (new Promise((resolve) => {
    
            firebase.database()
            .ref(`/users/${users}`)
            .on('value', snapshot => {
    
                /*
                When value recieved, resolve the promise for
                this user with val()
                */    
                resolve(snapshot.val());
            });
        }));
    
        /*
        Add value for this user to the resulting user_list_item
        */
        user_list_temp.push(user_list_item);
    }
    
    console.log(user_list_temp);
    

    此代码假定封闭函数被定义为使用async 关键字的异步方法,看到await 关键字在for..of 循环中使用。希望对您有所帮助!

    【讨论】:

      【解决方案2】:

      async/await 可以与firebase 一起使用

      这就是我通常制作Promise.all的方式

      const db = firebase.database();
      let user_list_temp = await Promise.all(arrWithKeys.map(async (users,i) => {
          const eventRef = db.ref(`users/${users}`);
          const snapshot = await eventref.once('value');
          const value = snapshot.value();
          return value;
        })
      );
      

      这篇文章对Promise.all和async/awaithttps://www.taniarascia.com/promise-all-with-async-await/的使用给出了相当好的解释

      这是我将如何重构您的新代码 sn-p 以便您不会混淆 promises 和 async/await

      let user_list_temp = await Promise.all(arrWithKeys.map(async (users,i) => {
        const eventRef = db.ref(`users/${users}`);
        const snapshot=  await eventRef.once('value');
        const value = snapshot.val();
        console.log(value);
        phone_user_list[0][users].name = value.name;    // should this be hardcoded as 0?
        phone_user_list[0][users].photo = value.photo;  // should this be hardcoded as 0?
        console.log(phone_user_list[0]); 
        return phone_user_list[0];        // should this be hardcoded as 0?
        })
      );
      console.log(user_list_temp); 
      

      这是一个使用 fetch 而不是 firebase 的简单示例:

      async componentDidMount () {
        let urls = [
          'https://jsonplaceholder.typicode.com/todos/1',
          'https://jsonplaceholder.typicode.com/todos/2',
          'https://jsonplaceholder.typicode.com/todos/3',
          'https://jsonplaceholder.typicode.com/todos/4'
        ];
        let results = await Promise.all(urls.map(async url => {
          const response = await fetch(url);
          const json = await response.json();
          return json;
        }));
        alert(JSON.stringify(results))
      }
      

      【讨论】:

      • 一定是很晚了。我再次对其进行了测试,但它并没有像我想象的那样工作......我已经更新了帖子。你知道为什么我仍然得到一个空数组吗?
      • 你混合了promises 和async/await 你不应该在Promise.all 中同时使用这两种方法
      • 我还错过了Promise.all前面的await
      • 我尝试了新的 firebase 选项,但没有成功。我将 .on 更改为 .once,它按我的意愿工作。你知道为什么吗?
      • 使用 once() 从数据库中获取一次值,而使用 on() 会继续监听数据的变化,直到你调用 off()。来自这篇文章中的评论stackoverflow.com/questions/47572171/…。 cmets 作者是 google 的一名工程师,从事 firebase 工作
      猜你喜欢
      • 2016-10-25
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 2016-12-18
      • 1970-01-01
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多