【问题标题】:React Native wait for function to finish before proceedReact Native 等待函数完成后再继续
【发布时间】:2021-05-19 11:29:55
【问题描述】:

我有以下代码:

const DuellScreen = () => {
...
 const [code, setCode] = useState("");
 const [keyExisting, setExi] = useState(true);
...
return (
...
 <BlockButton
                text="Apply"
                onPress={() => {
                  keyExists(code, setExi)
                  if (keyExisting == true) {
                    Alert.alert("Game joined");
                  } else if (keyExisting == false) {
                    Alert.alert(
                      "Game does not exist or someone has already joined"
                    );
                  }
                }}
              />
...)

我的函数 keyExists 正在使用 firebase/firestore,因此可能需要一段时间才能更新 keyExisting。 这导致我的 if 语句的错误结果。 这也是一个标志,即第一次按下按钮时,if 语句始终为“真”,因为那是初始状态。如果我将初始状态更改为“false”,则第一次单击按钮后 if 语句的结果始终为“false”。 所以第一次点击按钮始终是初始状态(useState),但应该在if语句之前更新...

如果需要,这也是我的 keyExists 函数:

export const keyExists = (setKey, keyExi) => {
  duettsRef
    .where("key", "==", setKey)
    .where("player1", "!=", firebase.auth().currentUser.uid)
    .where("player2", "==", "")
    .limit(1)
    .get()
    .then((querySnapshot) => {
      keyExi(!querySnapshot.empty);
      if (!querySnapshot.empty) {
        querySnapshot.docs[0].ref.update({
          player2: firebase.auth().currentUser.uid,
        });
      }
    })
    .catch((e) => console.log(e));
};

我做错了什么?

【问题讨论】:

  • 你想等到你的功能完成吧?你可以使用 promise 来等待代码执行你的函数,然后继续。如果我的方向正确,请告诉我,我可以在这方面为您提供更多帮助。
  • @DipanSharma 是的,没错。我将非常感谢您提供更多帮助

标签: reactjs firebase react-native google-cloud-firestore


【解决方案1】:

我认为你在这里混合了几件事。

firebase SDK 是异步的,因此您调用的函数会返回一个承诺。 使用 Promise 有两种方法,可以将它与 .then .catch 语句一起使用,也可以在带有关键字 await 的异步函数中使用它。

您的代码正在做一些非常奇怪且可能错误的事情:您正在为您的 keyExists 函数提供来自 useState 钩子的设置器,并且您希望在调用您的 keyExists 后直接使用此值,这是不可能的。 您的语句if (keyExisting == true) 将在您的代码到达.then((querySnapshot) 之前执行。

const [keyExisting, setExi] = useState(true); 此处的钩子为您提供了一个值和一个 setter,当您使用 setExi setter 时,您正在做两件事:1- 为下一次渲染设置 keyExisting 的值 2- 触发新的渲染你的组件。如果您有一个调用setExi 然后使用keyExisting 的函数,它在设置新值之前仍将具有先前的值。

你可以这样做:

const DuellScreen = () => {
...
 const [code, setCode] = useState("");
 const [keyExisting, setExi] = useState(true);
...
return (
...
 <BlockButton
                text="Apply"
                onPress={async () => {
                  try {
                    const exist = await keyExists(code);
                    if (exist == true) {
                      Alert.alert("Game joined");
                    } else if (keyExisting == false) {
                      Alert.alert(
                        "Game does not exist or someone has already joined"
                      );
                    }
                  } catch(e) {
                    console.log(e)
                  }
                }}
              />
...)

export const keyExists = (setKey, keyExi) => {
  return duettsRef
    .where("key", "==", setKey)
    .where("player1", "!=", firebase.auth().currentUser.uid)
    .where("player2", "==", "")
    .limit(1)
    .get()
    .then((querySnapshot) => {
      
      if (!querySnapshot.empty) {
        querySnapshot.docs[0].ref.update({
          player2: firebase.auth().currentUser.uid,
        });
      }

      return (!querySnapshot.empty);
    })
    .catch((e) => console.log(e));
};

但是您可能应该将您的 keyExists 拆分为两个函数:一个仅告诉您您的密钥是否存在,另一个用于更新您的 firestore 数据库。 另一件可能值得做的事情是使用某种活动指示器来锁定您的按钮,知道您的用户可以多次点击您的按钮,每次点击都会触发对您的 keyExists 函数的新调用。

【讨论】:

  • 我试过了,但它不起作用。我打印了:const exist = await keyExists(code); console.log("EXIST: " + exist); 但它未定义。
  • 抱歉,上面的代码中缺少返回值。您应该在最后一个 .then 中返回整个 firebase 语句,然后,这应该返回一个带有布尔值的承诺。无论如何,不​​要完全复制粘贴上面的内容,而是看看 promise 是如何工作的:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 这是一个快速答案,让您了解如何处理异步 firestore 调用。
  • 没问题。我现在尝试将其拆分为 2 个功能。它的工作很好,除了一件事。它总是返回“假”...var opponent = false; 然后像上面一样...。.then((querySnapshot) =&gt; {if(!querySnapshot.empty){opponent = true; }})return opponent;};
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 2019-11-01
  • 2021-05-06
  • 2021-05-21
  • 2016-12-01
相关资源
最近更新 更多