【问题标题】:Firebase - waiting for data from async database callFirebase - 等待来自异步数据库调用的数据
【发布时间】:2023-03-24 06:32:01
【问题描述】:

我正在尝试通过 2 个数据库调用从 firebase 获取一些数据。 我只为 1 个用户获取帐户的策略如下:

  • 获取登录用户的所有帐号
  • 新的 fetch 调用以获取帐户数组(及其所有数据)
  • 使用完整数组调度调用

我的 firebase 结构如下所示。

我的问题是第二个 fetch 调用总是最后完成。

export const fetchAccounts = () => {
   return (dispatch, getState) => {
      const accounts = [];
      const uid = getState().auth.uid;

      return database.ref(`users/${uid}/accounts`).once('value').then((snapshot) => {
         snapshot.forEach((element) => {
            database.ref(`accounts/${element.key}`).once('value').then((snapshot) => {
               accounts.push(snapshot.val());
               console.log('snapshot: ', accounts);
            })
         });
         console.log('Acc 1:', accounts);
      }).then(() => {
         console.log('Acc 2:', accounts)
      })

      // dispatch call with full array
   }
};

我正在从主文件调用操作

  reduxStore.dispatch(fetchAccounts()).then(()=>{
     renderApp();
  });

是否可以等待两个数据库调用完成,然后使用完全填充的数组调用调度函数?欣赏任何想法。

【问题讨论】:

    标签: javascript reactjs asynchronous firebase-realtime-database


    【解决方案1】:

    您的第一个 then() 不会返回任何内容,因此第二个 then() 将立即触发,这就是您在控制台中看到的内容。然而,请求的循环是异步的,尚未完成

    创建一个 promise 数组并使用 Promise.all(),这样第二个 then() 在循环中的请求全部完成之前不会触发。

    export const fetchAccounts = () => {
       return (dispatch, getState) => {
          const accounts = [];
          const uid = getState().auth.uid;
    
          return database.ref(`users/${uid}/accounts`).once('value').then((snapshot) => {
             const accountPromises =[];// array to store promises
    
             snapshot.forEach((element) => {
                // reference promise to pass into array
                const request = database.ref(`accounts/${element.key}`).once('value').then((snapshot) => {
                   accounts.push(snapshot.val());
                   console.log('snapshot: ', accounts);
                });
                // push request promise to array
                accountPromises.push(request)
    
             });
             console.log('Acc 1:', accounts);// accounts should still be empty here since requests are in progress
             // return promise that doesn't resolve until all requests completed
             return Promise.all(accountPromises);
          }).then(() => {
             // shouldn't fire until all the above requests have completed
             console.log('Acc 2:', accounts);
             return accounts // return array to use in next `then()`
          })
    
          // dispatch call with full array
       }
    };
    

    【讨论】:

    • 非常感谢! cmets 确实对理解逻辑有很大帮助:)
    • 请记住,如果其中任何一个请求失败,promise.all() 将无法解决,因此您需要添加额外的 catch() 以进行错误处理
    猜你喜欢
    • 2018-01-17
    • 1970-01-01
    • 2017-02-04
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    • 2016-02-16
    相关资源
    最近更新 更多