【问题标题】:Problem with updating a variable in Vue.js在 Vue.js 中更新变量的问题
【发布时间】:2020-05-08 19:24:16
【问题描述】:

我正在使用 Vue.js 创建一个 Web 应用程序(这是我第一次使用它)。该应用程序基本上是一个多用户实时测验,每个用户都必须选择一个角色并回答与他的角色相关的问题。我使用 Cloud Firestore 数据库中的集合来存储与每个角色相关联的问题以及与每个问题相关联的答案。此外,每个答案的特点是一个字段“nextQuestion”包含下一个要可视化的问题的 id,一个字段“nextUser”包含与这个新问题相关的下一个用户的 id(这些字段用于查询选择下一个问题及其可能的答案)和一个布尔字段“默认”,如果为真,则在用户未在设定时间内回答问题的情况下选择的答案(其他字段指示文本答案)。我通过查询获得问题和答案,以便在 webapp 上将它们可视化。 我的问题与用户在设定的时间内没有回答问题的情况有关(同时如果用户在设定的时间内选择了答案,我没有问题)。当回答的时间到期时,我调用这个函数:

CountTerminated: function () {    

  if(this.optionSelected == false){   //optionSelected is a component variable that informs if a user has selected or not an answer

    this.onNotSelectedAnswer(this.getDefaultAnswer())

  }

  else{
              this.onClickButtonConfirm()  //function called if the user selects an answer within the set time
      }  

}

getDefaultAnswer() 函数获取与当前问题关联的默认答案的字段(其中“nextUser”和“nextQuestion”)(通过查询)并通过变量返回:

 getDefaultAnswer(){

            var data 
            db.collection("Utenti").doc(this.userId).collection("Domande").doc(this.questionId).collection("Risposte").where("default","==",true).get().then(querySnapshot =>{

                querySnapshot.forEach(doc=>{


                data = doc.data()

              })
            })

            return data

          },

onNotSelectedAnswer(data)函数主要接收getDefaultAnswer()返回的值,将“data”赋值给组件变量answerId,并更新组件变量“userId”的值(告知角色的作用)必须回答当前问题的用户),组件变量“questionId”的值(包含当前问题的 id)和 questionValue 的值(包含当前问题的文本)使用函数 setUserId() , setQuestionId(), setQuestionValue()

onNotSelectedAnswer: function(data){


            if(this.userChoice == this.userId){

              this.answerId = data


            this.setUserId(this.answerId.nextUser)
            this.setQuestionId(this.answerId.nextQuestion)
            this.setQuestionValue()

            this.optionSelected = false
            this.answers=[]
            this.isActive = ""
            this.getAnswers()   //function used to query  (using updated values of userId and questionId variable) the DB to obtain a question and its related possible answers
            var a = this.channel.trigger('client-confirmEvent',{ user:  this.userId, question : this.questionId, questionval: this.questionValue})   
            console.log(a)


            }

 }

问题与 onNotSelectedAnswer() 函数中的 answerId 是“未定义”而不是包含查询结果以及我将用于上传新问题的数据有关。我不明白是哪个错误,希望您能帮助我。

【问题讨论】:

  • 在 getDefaultAnswer() 上,我建议你在使用你的方法之前检查 querySnapshot 变量是否不为空。

标签: javascript vue.js vuejs2 google-cloud-firestore vue-component


【解决方案1】:

问题在于 Firestore 查询是异步的,但您在继续之前没有等待响应。实际上,您拥有的是:

getDefaultAnswer () {
  var data 

  // This next bit is asynchronous
  db.doLotsOfStuff().then(querySnapshot => {
    // This callback won't have been called by the time the outer function returns
    querySnapshot.forEach(doc => {
      data = doc.data()
    })
  })

  return data
},

对 Firestore 的异步调用将在后台进行。同时getDefaultAnswer中的其余代码将继续同步运行。

因此,当代码到达return data 时,then 回调中的任何代码都不会运行。您可以通过输入一些控制台日志来确认这一点,以便查看代码运行的顺序。

使用then 处理异步代码是Promises 的一个特性。如果您还不熟悉 Promises,那么您应该在继续之前详细研究它们。以下是众多可用指南之一:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

底线是您不能强制getDefaultAnswer 方法等待异步操作完成。相反,您可以做的是返回一个合适的 Promise,然后在调用 onNotSelectedAnswer 之前等待该 Promise 解决。它可能看起来像这样:

getDefaultAnswer () {
  // We return the Promise chain from getDefaultAnswer
  return db.doLotsOfStuff().then(querySnapshot => {
    var data = null

    // I have assumed that forEach is synchronous
    querySnapshot.forEach(doc => {
      data = doc.data()
    })

    // This resolves the Promise to the value of data
    return data
  })
},

很重要的一点是,getDefaultAnswer 方法并没有尝试返回数据的值。相反,它返回一个 Promise,它将 resolve 到数据的值。

CountTerminated 中,您可以像这样使用它:

this.getDefaultAnswer().then(defaultAnswer => {
  this.onNotSelectedAnswer(defaultAnswer)
})

或者如果您愿意:

this.getDefaultAnswer().then(this.onNotSelectedAnswer)

后者更简洁,但不一定更清晰。

您也可以使用async/await 编写它,但我不建议您尝试使用async/await,除非您牢牢掌握 Promise 的工作原理。虽然async/await 对于整理代码非常有用,但它只是 Promises 的一个薄包装,您需要了解 Promises 才能调试任何问题。

我上面建议的代码应该可以工作,但是在等待异步请求完成时会有延迟。在这种延迟中,可能会发生一些事情,例如用户可能点击一个按钮。这可能会让你陷入更多问题。

另一种方法是更快地加载默认答案。不要等到你真正需要它。也许在显示问题后立即加载它。将结果保存在可访问的地方,可能在合适的data 属性中,以便在您需要时立即可用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多