Changing global variables within a POST request

I am currently developing a quiz application for the Noops Challenge on Github, utilizing the Fizzbot API available at Noops Challenge.

To keep track of the current question and the next question URLs, I have defined global variables to store and assemble them.

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

There is a submit function in my app that sends a POST request to the server. If the answer is correct, it then retrieves the URL of the next question.

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;
        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 the submit button, there is also a next button in the quiz app. Even after answering correctly and submitting, clicking the next button still logs the same URL - .

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

The issue seems to be related to the asynchronous behavior of the POST request. I need to find the best solution to resolve this problem. For a more detailed example illustrating the situation, check out the complete snippet provided below.

Answer №1

Global variables are stored in the window object. The keyword this has the ability to reference not only the window object but also various other objects. It's worth noting that neglecting to use this may still result in accessing a global variable.

The following code snippet operates within the global context:

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

In this instance, this is equivalent to window, thereby constructing this.url from the global variables.

The context shifts 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 points to the xhttp object. By assigning this.question, you are essentially introducing a new property on xhttp and utilizing that value to update the text within <h5 id="question">. This setup works as intended, although it doesn't modify your global question variable.

Once again, a global variable is utilized:

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

A similar scenario unfolds when utilizing 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 generate properties within this newly instantiated xhttp object. However, since this wasn't prefixed before baseurl, and there's no local variable by that name, the global variable will be utilized! Essentially, implicitly executing:

xhttp.url = window.baseurl + xhttp.nextQuestion

This results in displaying a completely new URL:

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

Nevertheless, the actual request continues to employ the original URL, as we're exiting the xhttp scope and relying on the unaltered global value here:

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

... and here:

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

To sum up: utilize window.url for setting the global value within another scope.

Information regarding 'this' on MDN

Answer №2

After diving deeper into the issue, I realized that the main challenge lied in managing variable scope rather than handling asynchronous operations in the code. To simplify my workflow and eliminate confusion with numerous this references, I decided to encapsulate most of my global variables within an object. This approach not only organized the code better but also improved clarity.

By utilizing an object with getters and setters, I found it much easier to access and manipulate all variables seamlessly across the codebase.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for utilizing the vuetify readonly prop while enabling the selection menu

In my project, I have a grid containing v-autocomplete components with the multiple attribute. To maintain clean formatting, I decided to show only a shortened version of the content using the selection slot feature provided below: <v-autocomp ...

Tips for obtaining the entire date and time on one continuous line without any breaks or separation

Is there a way to retrieve the current date and time in the format of years, months, days, hours, minutes, seconds, and milliseconds like this? 201802281007475001 Currently, I am getting something like: 2018418112252159 This is my code so far: var dat ...

The function for the "load next page" action in ngInfiniteScroll is continuously triggered

After attempting to implement infinite scrolling using the "loading remote data" example from the ngInfiniteScroll website, I am facing a problem. The function nextPage() is being called continuously until all records have been loaded (controlled by an of ...

Using setTimeout with jQuery.Deferred

I decided to experiment with jQuery Deferred and setTimeout by creating a basic list. <ul> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> In my script, I ...

Having trouble getting Vuejs to work when appending an element to Fullcalender

Hi there, I am facing an issue where appending a custom button to a full calendar event is not working properly with Vue.js methods. It works fine with core JavaScript, but I really want it to work with Vue.js methods. Any ideas on how I can achieve this? ...

The power of Three.js comes alive when utilizing appendChild and returning elements

I recently encountered an interesting issue that I managed to resolve, but out of sheer curiosity, I would love for someone to shed some light on why this problem occurred. Below is the snippet of my HTML code: <!DOCTYPE html> <html> < ...

Include certain tags to the content within the text apart from using bbcode tags

I need help with a project involving a BBCODE editor that can switch between a WYSIWYG editor and a code editor. The visual editor is designed with a drag-and-drop block system for elements like pictures and text. In the visual editor, when a user drags ...

A bug in the modal dialog is causing it to disregard the value of

I want to transfer certain modal properties in this manner service.confirm = function(message, confirmProperties) { return $uibModal.open({ templateUrl: 'app/modal/alert/alert.tpl.html', controller: 'alertCon ...

Unable to return true within an ajax call

Currently, I am working on implementing form validation which involves checking if the email address exists to return either true or false. However, the issue I am facing is that it does not return true, hence preventing me from validating other fields aut ...

What is the process for dynamically incorporating JavaScript files during compilation to serve as input for browserify?

Within our project's structure, there exists a directory housing multiple js files. The possibility of adding or removing these files later on is present. Currently, we have a file named main.js where each file is imported and a map is created (using ...

Continuously encountering a Login Required message while attempting to upload a file on Google Drive

I am currently developing a chrome extension that is designed to intercept specific downloads, like .doc and .docx files, and automatically upload them to a designated folder in Google Drive. Below is the manifest for this extension: { // Manifest det ...

Generating HTML content from XML data with the help of JavaScript

Challenge: Attempting to display one question and its four corresponding answers at a time from an XML file. JavaScript code: var xmlDoc, quest, ans, i, n; xmlDoc = loadXMLDoc("questions.xml"); quest = xmlDoc.getElementsByTagName('main'); do ...

The usage of arrow functions in ReactJS programming

I'm working on a React component that has the following structure: import React, { PropTypes, Component } from 'react'; import { Accordion, Panel, PanelGroup, Table } from 'react-bootstrap'; const FormCell = ({ data }) => ( ...

Working with Three.js: Retrieving an object post-loading using GLTF Loader

Is there a method in three.js using the GLTF loader to access an object for transformations after it has been loaded? It seems like attempting this approach does not yield results gltf.scene.position.set(10,10,10) Sample Code: function getObject(){ ...

Issue with making Flickr API request using XMLHttpRequest receiving an unsuccessful response

I'm having issues trying to retrieve a JSON list from Flickr using plain JavaScript and XMLHttpRequest. Here is an example of an AJAX call without a callback function that is not functioning properly: var url = "https://api.flickr.com/services/feed ...

The setInterval function does not function properly in IE8 when set to 0

I have a function called changeColor that updates the styling of certain elements in my HTML. In order to apply this function, I am using a timer like so: var timer = setInterval(changeColor,0); The issue I am encountering is that setting the time interv ...

The functionality of a switch statement relies on the presence of a React-Router

Is there a way to dynamically change the text in a paragraph based on which Route is currently enabled? I tried using a switch statement, but I'm unsure of how to implement it. Any suggestions or ideas? import React from 'react'; import &ap ...

Following an AJAX post within the MVC framework, the URL becomes excessively lengthy

http://localhost:53435/Blog/BlogIndex?title=blog+title&seo=seo&content=%3Cp%3Econtent%3C%2Fp%3E%0D%0A the URL listed above Whenever I click the save button, the page refreshes and the URL appears like that. I do not want it, how can I resolve th ...

Rails assets folder is not directed to the specified directory in the layout file

I have a dilemma in the application layout where I'm referencing assets (js, css, and img) in the public/assets/... directory. For example: <link href='assets/images/meta_icons/apple-touch-icon-144x144.png' rel='apple-touch-icon-pre ...

Invalid Resize Argument Causes Background to Not Appear on IE Browser

I have encountered a problem where the background (BG) image is not appearing in Internet Explorer (IE). I am struggling to find a solution for this issue. BG Problem Below is the code snippet showing how I implemented the background image. I have used a ...