开发者问题收集

打开应用程序时未从 Firebase 获取数据

2021-01-09
89

我正在尝试从 firebase 获取数据,但它在应用程序加载时返回空值,但如果我在该文件上编辑某些内容,即使是注释行,那么数据也会加载并且应用程序会运行,我希望当应用程序打开时,所有数据都应该来自 firebase 以运行应用程序。以及如何以相反的顺序排列“grabbedData”,尝试了 grabbedData.reverse(),但没有用。

  const Getdata = async () => {
    let grabbedData = [];

    await firebase
      .database()
      .ref(`/users/`)
      .orderByKey()
      .on("value", (snapshot, key) => {
        // console.log("snapshot....", snapshot);
        grabbedData.push(snapshot.val());
      });
    setUserdata(grabbedData);
    console.log("grabbedData", grabbedData); // empty value here :(
    if (grabbedData) {
      let getfranchiseuid = "";
      Object.keys(grabbedData).map(function (key) {
        let y = grabbedData[key];
        Object.keys(y).map(function (key2) {
          let x = y[key2];
          if (key2 === uid) {
            getfranchiseuid = x.franchiseuid;
          }
        });
      });

      if (getfranchiseuid) {
        let customerList1 = [];
        firebase
          .database()
          .ref(`/serviceProvider/${getfranchiseuid}/franchise/customers`)
          .orderByKey()
          .on("value", (snapshot) => {
            customerList1.push(snapshot.val());
          });
        setCustomerList(customerList1);
        console.log("customerList1customerList1", customerList1);
      }
    }
  };

  useEffect(() => {
    var unsubscribe = firebase.auth().onAuthStateChanged(function (user) {
      if (user) {
        storeUser({ user });
        setUser(user);
        setEmail(user.email);
        setUid(user.uid);
      } else {
        // No user is signed in.
      }
    });
    unsubscribe();
    Getdata();
  }, []);
1个回答

数据是从 Firebase 异步加载的。由于这可能需要一些时间,您的主要 JavaScript 代码将继续运行,以便用户可以在数据加载时继续使用应用。然后,当数据可用时,将使用该数据调用您的回调。

这在您的代码中意味着(例如)现在您的 setUserdatagrabbedData.push(snapshot.val()) 运行之前被调用,因此您正在设置任何空的用户数据。通过在代码上设置一些断点并在调试器中运行它,或者通过添加日志记录并检查其输出的顺序,您可以最轻松地看到这一点。

console.log("1");
await firebase
  .database()
  .ref(`/users/`)
  .orderByKey()
  .on("value", (snapshot, key) => {
    console.log("2");
  });
console.log("3");

运行此代码时,输​​出将是:

1

3

2

这可能不是您所期望的,但它完全正确并且确实解释了您的问题。


此问题的解决方案始终相同: 任何需要数据库数据的代码都必须位于回调 内部 ,或从那里调用。

例如:

await firebase
  .database()
  .ref(`/users/`)
  .orderByKey()
  .on("value", (snapshot, key) => {
    grabbedData.push(snapshot.val());
    setUserdata(grabbedData);
  });

这将确保每当您更新 grabbedData 时都会调用 setUserdata


由于您有更多依赖于 grabbedData 的代码,因此也必须在回调中。因此整个 if (grabbedData) {{ 块需要移动,其他的可能也需要移动。如果您继续应用上述解决方案,代码将开始工作。

对于刚开始调用异步云 API 的开发人员来说,这是一个非常常见的问题,因此我强烈建议您阅读以下其他一些答案:

Frank van Puffelen
2021-01-09