Firestore承诺无法解决

时间:2020-07-01 20:20:04

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

我有一个非常奇怪的错误。有时,当我提交表单时,“ 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之后,我尝试实现一个asynchoronus SubmitHandler。但是,这导致甚至没有调用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;
  });

}

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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
  });
  
}