在POST请求中修改全局变量

时间:2019-07-01 16:35:10

标签: javascript ajax asynchronous

因此,我目前正在尝试使用他们的Noops Challenge为Github的Fizzbot API创建一个简单的测验应用。

我正在将当前问题和下一个问题的URL存储并组装到全局变量中。

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

我有一个提交功能,可以将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);

}

除了我的提交按钮外,我还有一个下一个按钮。提交正确答案后,以下功能仍将https://api.noopschallenge.com/fizzbot/questions/1打印到日志中。

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

我很确定它与POST请求的异步性质有关,但不确定解决它的最佳方法是什么。我已经发布了一个更完整的代码段,用于说明正在发生的事情。

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>

2 个答案:

答案 0 :(得分:0)

全局变量存储在window对象中。 this可以引用window以及几乎任何其他对象。另外,不使用this也会为您提供一个全局变量。

这将在全局上下文中运行:

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

这里this === window,因此this.url是根据您的全局变量构建的。

上下文在这里更改:

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

在这里,this指向xhttp对象。设置this.question时,您将在xhttp上创建一个新属性,并使用该值设置<h5 id="question">文本。这行得通,只是不会更改全局question变量。

这再次使用了全局变量:

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

使用“提交”按钮时会发生类似的事情:

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;

this.nextQuestionthis.url都在此(新!)xhttp对象中创建属性。但是,由于您没有将this.放在baseurl的前面,并且没有使用该名称的局部变量,因此将使用全局变量!因此,您暗中在执行此操作:xhttp.url = window.baseurl + xhttp.nextQuestion

这就是为什么它将显示一个不错的新完整URL:

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

但是同样,请求本身仍然使用初始URL完成,因为我们离开了xhttp范围,并在这里使用了从未更改的全局值:

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

...这里:

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

长话短说:使用window.url在另一个作用域内设置全局值。

About 'this' on MDN

答案 1 :(得分:0)

似乎它与实际变量范围的关系比与代码的异步方面的关系更多。与其处理一堆凌乱的this引用,我只是将我的大多数全局变量放在一个对象中,该对象无论如何最终变得更加有意义。

使用带有getter和setter的对象,我可以访问整个代码中的所有变量。