Firebase - 等待来自异步数据库的数据

时间:2018-03-17 20:03:44

标签: javascript reactjs asynchronous firebase-realtime-database

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

  • 获取登录用户的所有帐号
  • 新的获取调用以获取一系列帐户(及其所有数据)
  • 使用完整数组发送电话

我的火力架结构看起来像这样。

enter image description here

我的问题是第二次提取呼叫总是在最后完成。

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

enter image description here

我正在调用主文件中的操作

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

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

1 个答案:

答案 0 :(得分:2)

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

创建一个promises数组并使用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
   }
};