【问题标题】:Firestore promise not resolvingFirestore 承诺未解决
【发布时间】:2020-10-22 08:49:52
【问题描述】:

我遇到了一个非常奇怪的错误。有时,当我提交表单时,“userId”cookie 不会更新。我想我已经把这个问题隔离出来了

return user.set({
    roomId: roomId,
    name: name
  }).then(() => alert("finished writing"))

当 cookie 未更新时,永远不会调用“完成写入”警报。我认为这与未解决的承诺有关,并且占用了线程,因此 .then 永远不会运行(因此带有 cookie 更新的 .then 永远不会运行)。但是,我不太了解承诺,也找不到可能阻碍它的原因。如果有人可以帮助我或指出错误,将不胜感激。代码如下:

function GamePage() {
  const {roomId} = useParams();
  const db = firebase.firestore();
  let history = useHistory();
  const [userIdExistsButWrongRoom, setUserIdExistsButWrongRoom] = useState(true);
  const userId = cookies.get('userId');
  useEffect(() => {
    if(!(typeof(userId)==="undefined")){
    db.collection("users").doc(userId).get().then(function(doc){
      if(doc.data().roomId === roomId){
          setUserIdExistsButWrongRoom(false);
        } 
      });
    }
  }, [db,roomId,userId]);

  if(cookies.get('roomId')===roomId){
    if(typeof(userId)==="undefined"){
      return (
        <div>
        <EnterName />
      </div>
      );
    } else {
        if(userIdExistsButWrongRoom){
          return (
            <div>
            <EnterName />
          </div>
          );
        } else {
          return (
            <div>
            <Game />
            </div>);
        }
      }
  } else {
    history.push("/");
    return (<div />);
  }
}

function EnterName() {
  const {roomId} = useParams();
  const [name, setName] = useState("");
  
  function handleChange(event) {
    setName(event.target.value);
  }
  function handleSubmit(event) {
    addNewUser(roomId,name).then(function(userId) {cookies.set('userId',userId)});
  }
  return (<form onSubmit={handleSubmit}>
    <label>
      Name:
      <textarea value={name} onChange={handleChange} />
    </label>
    <input type="submit" value="Submit" />
  </form>);
}


function Game() {
  const {roomId} = useParams();
  return (<div>
    <h1>
    {roomId}
    </h1>
  </div>);
}


//Add a new user with server generated unique ID, and the given room ID to the database
//Returns the doc
function addNewUser(roomId,name) {
  const db = firebase.firestore();
  const user = db.collection("users").doc()
  const userId = user.id;
  alert(userId);
  return user.set({
    roomId: roomId,
    name: name
  }).then(() => alert("finished writing"));
  
}

编辑

Oliver's answer 之后,我尝试实现一个异步提交处理程序。但是,这导致 addNewUser 函数甚至没有被调用。我发现了这个问题javascript async await Submitting a form with onsubmit using Promise,这表明异步 submitHandler 的问题在于它总是返回一个 Promise,因此它在 Promise 解决之前提交。我尝试实施他们提出的修复方案(如下),但现在又回到了原来的问题,但现在一直都是!

function EnterName() {
  const {roomId} = useParams();
  const [name, setName] = useState("");
  
  function handleChange(event) {
    setName(event.target.value);
  }
  async function handleSubmit(event) {
    let userId = await addNewUser(roomId, name);
    alert("test");
    cookies.set('userId',userId);
  }
  function submit(event){
    handleSubmit(event);
    return false;
  }
  return (<form onSubmit={submit}>
    <label>
      Name:
      <textarea value={name} onChange={handleChange} />
    </label>
    <input type="submit" value="Submit" />
  </form>);
}


function Game() {
  const {roomId} = useParams();
  return (<div>
    <h1>
    {roomId}
    </h1>
  </div>);
}


//Add a new user with server generated unique ID, and the given room ID to the database
//Returns the doc
async function addNewUser(roomId,name) {
  const db = firebase.firestore();
  const user = db.collection("users").doc()
  const userId = user.id;
  alert(userId);
  return user.set({
    roomId: roomId,
    name: name
  }).then(() => {
    alert("finished writing");
    return userId;
  });

}

【问题讨论】:

    标签: javascript reactjs firebase google-cloud-firestore promise


    【解决方案1】:

    我终于修好了。问题出在没有覆盖 React 中 onSubmit 的默认行为。所以页面在承诺完成之前重新加载,从而切断了线程。当我添加 event.preventDefault(); 时,此问题已修复。

    这是现在可以使用的固定代码:

    function EnterName(props) {
      const {roomId} = useParams();
      const [name, setName] = useState("");
      
      function handleChange(event) {
        setName(event.target.value);
      }
      function handleSubmit(event) {
        addNewUser(roomId,name).then(function(user) {
          cookies.set('userId',user.id);
          alert("finished cookies");
          props.userExists(false);
        });
        event.preventDefault();
        return false;
      }
      return (<form onSubmit={handleSubmit}>
        <label>
          Name:
          <textarea value={name} onChange={handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>);
    }
    
    
    function Game() {
      const {roomId} = useParams();
      return (<div>
        <h1>
        {roomId}
        </h1>
      </div>);
    }
    
    
    //Add a new user with server generated unique ID, and the given room ID to the database
    //Returns the doc
    function addNewUser(roomId,name) {
      const db = firebase.firestore();
      return db.collection("users").add({
        roomId: roomId,
        name: name
      });
      
    }
    

    【讨论】:

      【解决方案2】:

      Promise 是异步的,因此您的处理可能会在它解决之前结束。使用await/async 让它等待。

      试试这个:

      function EnterName() {
        const {roomId} = useParams();
        const [name, setName] = useState("");
        
        function handleChange(event) {
          setName(event.target.value);
        }
        async function handleSubmit(event) {
          let userId = await addNewUser(roomId, name);
          cookies.set('userId',userId);
        }
        return (<form onSubmit={handleSubmit}>
          <label>
            Name:
            <textarea value={name} onChange={handleChange} />
          </label>
          <input type="submit" value="Submit" />
        </form>);
      }
      
      
      function Game() {
        const {roomId} = useParams();
        return (<div>
          <h1>
          {roomId}
          </h1>
        </div>);
      }
      
      
      //Add a new user with server generated unique ID, and the given room ID to the database
      //Returns the doc
      async function addNewUser(roomId,name) {
        const db = firebase.firestore();
        const user = db.collection("users").doc()
        const userId = user.id;
        alert(userId);
        return user.set({
          roomId: roomId,
          name: name
        }).then(() => {
          alert("finished writing");
          return userId;
        });
      }
      

      【讨论】:

      • 感谢您的建议,我也没有想过将 handleSubmit 函数设为异步。我试过这个,不幸的是它使问题变得更糟 - 现在这个错误总是发生,而不是只是偶尔发生。
      • 我改了。再试一次;)
      • 谢谢,和以前一样。每次我害怕时都会发生错误
      • addNewUser 的等待永远不会结束,或者至少如果我在它永远不会触发之后发出警报。
      • 我刚刚意识到这两个选项的错误与以前不同,它甚至没有调用 addNewUser。我已经编辑了我的答案以包含我尝试过的其他内容
      猜你喜欢
      • 1970-01-01
      • 2020-03-16
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-24
      • 2018-06-26
      相关资源
      最近更新 更多