简体   繁体   English

在POST请求中修改全局变量

[英]Modifying global variables inside of POST request

So I'm currently trying to make a simple quiz app for Github's Noops Challenge using their Fizzbot API . 因此,我目前正在尝试使用Fizzbot API为Github的Noops Challenge制作一个简单的测验应用程序。

I am storing and assembling the URL of the current question and next question in global variables. 我正在全局变量中存储和组装当前问题和下一个问题的URL。

var baseurl = "https://api.noopschallenge.com";
var nextQuestion = "/fizzbot/questions/1";
var url = "";

I have a submit function that sends a POST request to the server and receives the URL of the next question if the answer is correct. 我有一个Submit函数,它将POST请求发送到服务器,并在答案正确的情况下接收下一个问题的URL。

function submit() {
    var answer = document.getElementById("answer").value;

    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {

            var response = JSON.parse(this.responseText);

        this.nextQuestion = response.nextQuestion; fizzbot
        this.url = baseurl + this.nextQuestion;

        console.log("Next Question: " + this.url);  
        }
    };

    xhttp.open("POST", this.url, true);
    xhttp.setRequestHeader("Content-type", "application/json");
    xhttp.send(answer);

}

In addition to my submit button, I have a next button. 除了我的提交按钮,我还有一个下一个按钮。 After submitting a correct answer, the below function still prints https://api.noopschallenge.com/fizzbot/questions/1 to the log. 提交正确答案后,以下功能仍将https://api.noopschallenge.com/fizzbot/questions/1打印到日志中。

function next() {
    console.log(this.url);
}

I am pretty sure it has something to do with the asynchronous nature of the POST request, but am not sure what the best way to solve it is. 我很确定它与POST请求的异步性质有关,但是不确定解决它的最佳方法是什么。 I've posted a more complete snippet for a functioning example of what's happening. 我已经发布了一个更完整的代码片段,以说明正在发生的事情。

 var question = ""; var baseurl = "https://api.noopschallenge.com"; var nextQuestion = "/fizzbot/questions/1"; var url = ""; function load() { this.url = this.baseurl + this.nextQuestion var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var response = JSON.parse(this.responseText); this.question = response.message; document.getElementById("question").innerHTML = this.question; } }; xhttp.open("GET", this.url, true); xhttp.send(); } function submit() { var answer = document.getElementById("answer").value; var responseObject = {answer: answer} var responseJSON = JSON.stringify(responseObject); var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var response = JSON.parse(this.responseText); this.nextQuestion = response.nextQuestion; this.url = baseurl + this.nextQuestion; document.getElementById("result").innerHTML = response.result; document.getElementById("nextQuestion").innerHTML = response.nextQuestion; console.log("Next Question: " + this.url); } }; xhttp.open("POST", this.url, true); xhttp.setRequestHeader("Content-type", "application/json"); xhttp.send(responseJSON); } function next() { console.log("URL to load: " + this.url); //GET request next question } 
 <!DOCTYPE html> <html> <head> <title>Noops Challenge | FizzBot Bot</title> <script src="Fizzbot.js" type="text/javascript"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <link rel="stylesheet" href="main.css"> </head> <body onload="load()"> <nav class="navbar navbar-dark bg-dark"> <a class="navbar-brand" href="#"> <img src="https://noopschallenge.com/static/animation/fizzbot/images/img_3.png" width="30" height="30" class="d-inline-block align-top" alt=""> FizzBuzz Quiz </a> <!-- <span class="navbar-brand mb-0 h1">FizzBuzz Quiz</span> --> </nav> <div class="container"> <div class="row" style="margin-top:5%;"> <div class="col-sm-2"></div> <div class="col-sm-8"> <div class="card"> <div class="card-header"> Question <span id="questionNumber">1</span> </div> <div class="card-body"> <h5 id="question" class="card-title">Filler Question</h5><br> Answer: <input type="text" id="answer"> <p class="card-text"><br> Result: <span id="result"></span><br> Next Question: <span id="nextQuestion"></span><br> </p> <button class="btn btn-primary" onclick="submit()" value="">Submit</button> <button class="btn btn-primary" onclick="next()" value="">Next</button> </div> </div> </div> <div class="col-sm-2"></div> </div> </div> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> </body> </html> 

Global variables are stored in the window object. 全局变量存储在window对象中。 this can refer to window as well as pretty much any other object. this可以引用window以及几乎所有其他对象。 Also, not using this might get you a global variable as well. 另外,不使用this可能也会使您获得全局变量。

This will run in the global context: 这将在全局范围内运行:

function load() {
  this.url = this.baseurl + this.nextQuestion

Here this === window , so this.url is built from your global variables. this === window ,因此this.url是根据全局变量构建的。

The context changes here: 上下文在这里更改:

  ...
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var response = JSON.parse(this.responseText);
      this.question = response.message;

      document.getElementById("question").innerHTML = this.question;
    }
  };

Here, this refers to the xhttp object. 在这里, this是指xhttp对象。 When setting this.question , you're creating a new property on xhttp and using that value to set the <h5 id="question"> text. 设置this.question ,您将在xhttp上创建一个新属性,并使用该值设置<h5 id="question">文本。 This works, it just doesn't change your global question variable. 这行得通,只是不会更改您的全局question变量。

This again uses the global variable: 再次使用全局变量:

  xhttp.open("GET", this.url, true);
  ...
}

Something alike happens when using the submit button: 使用提交按钮时会发生类似的事情:

function submit() {
  ...
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var response = JSON.parse(this.responseText);

      this.nextQuestion = response.nextQuestion;
      this.url = baseurl + this.nextQuestion;

Both this.nextQuestion and this.url create properties in this (new!) xhttp object. this.nextQuestionthis.url都在此xhttp对象中创建属性。 However, since you didn't put this. 但是,由于您没有放this. in front of baseurl , and there's no local variable with that name, the global variable will be used! baseurl前面,并且没有具有该名称的局部变量,将使用全局变量! So, implicitly you're doing this: xhttp.url = window.baseurl + xhttp.nextQuestion 因此,您暗中在执行此操作: xhttp.url = window.baseurl + xhttp.nextQuestion

That's why this will show a nice new full URL: 这就是为什么它将显示一个不错的新完整URL:

      console.log("Next Question: " + this.url);
    }
  };

But again, the request itself is still done using the initial URL, since we're leaving the xhttp scope and using the never changed global value here: 但是同样,请求本身仍然使用初始URL完成,因为我们离开了xhttp范围,并且在这里使用了从未更改的全局值:

  xhttp.open("POST", this.url, true);
  ...
}

... and here: ... 和这里:

function next() {
  console.log("URL to load: " + this.url);
  //GET request next question
}

Long story short: use window.url to set the global value inside another scope. 长话短说:使用window.url在另一个作用域内设置全局值。

About 'this' on MDN 关于MDN上的“ this”

It seems like it had more to do with actual variable scope than it had to do with the async aspect of the code. 似乎它与实际变量作用域的关系远大于与代码异步方面的关系。 Instead of dealing with a bunch of messy this references, I just put most of my globals inside of an object which ended up making more sense anyways. 相反,处理一堆凌乱的this引用,我只是把我的大部分全局的,其最终目的让更多的意义反正物体内部。

Using an object with getters and setters I am able to access all of my variables throughout the code. 通过使用带有getter和setter的对象,我可以访问整个代码中的所有变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM