Изменение глобальных переменных внутри запроса POST - PullRequest
0 голосов
/ 01 июля 2019

Итак, я сейчас пытаюсь создать простое приложение для викторины для 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 голосов
/ 05 июля 2019

Кажется, что это больше связано с фактической областью действия переменных, чем с асинхронным аспектом кода.Вместо того, чтобы иметь дело с кучей беспорядочных this ссылок, я просто поместил большую часть своих глобальных переменных в объект, который в любом случае имел больше смысла.

Используя объект с геттерами и сеттерами, я могу получить доступ ко всем моим переменным в коде.

0 голосов
/ 02 июля 2019

Глобальные переменные хранятся в объекте 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.nextQuestion, и this.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, чтобы установить глобальное значение внутри другой области.

Об этом на MDN

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...