等待所有 firebase 调用使用 map 函数完成

Posted

技术标签:

【中文标题】等待所有 firebase 调用使用 map 函数完成【英文标题】:Waiting for all firebase call to finish with map function 【发布时间】: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

【问题讨论】:

【参考方案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.allasync/awaithttps://www.taniarascia.com/promise-all-with-async-await/的使用给出了相当好的解释

这是我将如何重构您的新代码 sn-p 以便您不会混淆 promisesasync/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))

【讨论】:

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

以上是关于等待所有 firebase 调用使用 map 函数完成的主要内容,如果未能解决你的问题,请参考以下文章

在反应中使用异步等待从firebase存储中检索图像

记录或调试 iOS 的 Firebase HttpMetric 跟踪调用(无需等待 12 小时)

Firebase 异步等待风格的云函数

如何只修改 react .map 函数中的一个元素?

TypeError: urls.map 不是 React 中的函数

Flutter Firebase Functions:调用函数时出错