In the world of coding, the trio of javascript, $.ajax,

I need help with iterating over an array and assigning a variable using a for loop. Here is the scenario:

function Person(name, status){
  this.name = name;
  this.status = status;
}

var status = [];
var array = ["bill","bob","carl","ton"];
function exAjax(function(){
 for(var i = 0; i < array.length; i++){
   var name = array[i];
   console.log(name); =====> This correctly outputs the name

   $.ajax({
     url: xxxxxxx,
     success: function(data){
       if(data.stream === null){
         var person = new Person(name, "dead");
         console.log(name); =====> Currently returns undefined until all persons are added

         status.push(person);       
       }
     }

   })
   name = "";
 }
})

The issue I'm facing is that the 'name' variable is not passing into the success function as expected. Shouldn't JavaScript traverse upwards to find the variable if it's not found in the current scope? When I try to console.log 'name', I get undefined! Scope experts, please guide me on what might be going wrong here?

Answer №1

To maintain the scope of the name variable, you can use .queue() and $.map(). It is also advisable to change the status array to an object with a property named status, which has a value of an array. This prevents any potential conflicts with this.status within the Person object.

You can also chain the .promise(/* queueName */) method to execute tasks within the .then() function once all functions in the specified queue, for example, "status", have been called and the length of the queue is equal to zero.

function Person(name, status){
  this.name = name;
  this.status = status;
}

var blob = new Blob(['{"stream":null}'], {type:"application/json"});
var url = URL.createObjectURL(blob);
// change `status` array reference, e.g., to `arr`
var arr = {status:[]};
var array = ["bill","bob","carl","ton"];

$(arr).queue("status", $.map(array, function(curr) {
  return function(next) {
    var name = curr;
    // do asynchronous stuff
    $.ajax({url:url, dataType:"json"})
    .then(function(data) {
       if(data.stream == null){
         var person = new Person(name, "dead");
         console.log(name, person);
         arr.status.push(person);
       }
    })
    .then(next) // call next function in `"status"` queue
  }
}))
.dequeue("status")
.promise("status")
// do stuff when all functions in `"status"` queue have completed,
// `"status"` queue `.length` is `0`
.then(function() {
   // `this` : `arr` as jQuery object
   // `this[0].status`: array containing objects pushed to `arr.status`
   console.log(this[0].status); // $(this).prop("status");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

jsfiddle https://jsfiddle.net/nnayjckc/2/


An alternative approach is to use $.when(), .apply(), and $.map() to achieve the same result.

function Person(name, status) {
  this.name = name;
  this.status = status;
}

var blob = new Blob(['{"stream":null}'], {
  type: "application/json"
});
var url = URL.createObjectURL(blob);
// change `status` array reference, e.g., to `arr`
var arr = {
  status: []
};
var array = ["bill", "bob", "carl", "ton"];

$.when.apply($, $.map(array, function(curr) {
  var name = curr;
  return $.ajax({
      url: url,
      dataType: "json"
    })
    .then(function(data) {
      if (data.stream == null) {
        var person = new Person(name, "dead");
        console.log(name, person);
        arr.status.push(person);
      }
    })
}))
.then(function() {
  console.log(arr.status)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">  
</script>

jsfiddle https://jsfiddle.net/nnayjckc/3/

Answer №2

The reason for this behavior is because the $.ajax function performs an asynchronous HTTP (Ajax) request. This means that your for loop will not wait for the success callback to finish before continuing with its iteration.

One possible solution is to make the $.ajax call synchronous by using the async: false option.

Reference from the jQuery documentation

async (default: true)
Type: Boolean
By default, all requests are sent asynchronously (i.e., set to true). If you require synchronous requests, set this option to false.

 for(var i = 0; i < array.length; i++){
   var name = array[i];
   console.log(name); // Correct name is displayed

   $.ajax({
     url: xxxxxxx,
     async: false,
     success: function(data){
       if(data.stream === null){
         var person = new Person(name, "dead");
         console.log(name); // Name is undefined in earlier iterations until the last one
         status.push(person);       
       }
     }

   })
   name = "";
 }
})

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

Using ASP.NET to bind Page.Header.DataBind() can lead to conflicts with angular service method calls

I'm encountering a strange issue with my ASP.NET master page and code behind. Whenever Page.Header.DataBind() is called, all the public methods on my angular service are executed as well. Below is a snippet of my angular service: myModule.service("m ...

Using ReactJS to Deconstruct Data within Class Components

I have a file named Context.js with the following content: const AppContext = createContext({ // ... color palette scheme color1: '#ADBDDB', color2: '#7F8EB2', color3: '#546287', color4 ...

What is the best way to establish a maximum value for variable inputs?

In my Vue form, I have dynamic inputs for issuing shares to shareholders. The user first registers the total amount of shares in the form, then starts issuing this total amount partially by adding dynamic inputs as needed. Finally, the form is submitted. M ...

Show a separate div in a block format if the data field contains a value

<span>{{pstCtrl.doctorProfile.boardCertification ? === 'Yes' : $yes.display-block}}</span> <span class="yes">Yes</span> span.yes { display:none; } In my Angular.JS project, the code snippet above is demonstra ...

Having difficulty handling redirections in Node.js

I am encountering a new issue with the code provided. My goal is to create a simple login system, but I am facing difficulties in redirecting users using res.redirect('/example'). When attempting to redirect users, the console.log indicates that ...

Avoid reloading the header component along with its APIs when navigating routes in React JS

I'm currently working on a web application using react js/next js and within it, I have various pages that make use of globally shared components like the Header and Footer. However, I am facing an issue where I want to prevent unnecessary re-renders ...

Tips for incorporating the .click function with an overlay

Having some trouble using the .click function in conjunction with jQuery Tools overlay. HTML: <p id="click">Click here:</p> <div class="pop"> <div> <p>Insert text here</p> </div> </div> jQuery func ...

JavaScript Closures can utilize a shared global setting object or be passed as an argument to individual functions

Looking for advice on the use of a global "settings object" in relation to JavaScript closures. Should I access it from within functions in the global scope or pass the object every time a function requires access? To provide context, here's a mockup ...

Trouble accessing onclick function

My dataSend AJAX function is not being called when I use the onclick event. I have checked in the Inspector of my browser and confirmed that the click handler is attached to it. However, when I set a breakpoint in the function using the Debugger, it never ...

Utilize the filtering feature within the Vue select module

I'm struggling to get the select filter to work properly in my Quasar application. When I open the select, there is no list displayed and no value gets selected. Can someone help me understand why it's not working? <q-select v-mo ...

Exploring each item within oData: A guide

After writing the code statement above, I am able to see the attached image. Now, my challenge is accessing the "label" property inside each object. How can I iterate through these objects and retrieve their "label" properties? item.getModel().oData; I a ...

Exploring AngularJS's Unique Features: Isolated Scope and Controller Connection

Currently, I am diving into Angular and endeavoring to develop a Phone Message Log application utilizing directives. The concept is simple - the user inputs a message, clicks a button, and it gets displayed in a "Message" log below. The challenge I'm ...

Website search bar - easily find what you're looking for

I've tested this code and it works well on the basintap page. However, I'm interested to find out how I can search for something when I'm on a different page instead? <?php $query = $_GET['query']; $min_length = 2; if(strlen($ ...

Implementing AngularJS directives with jQuery

Utilizing Jquery Selectric to enhance the select box in my AngularJS app led me to create a directive for rendering the element. Below you'll find the directive code along with how it's implemented. The Directive: angular.module('shoeReva ...

Having trouble sending AJAX select options with Choices.js

I'm currently utilizing Choices.js (https://github.com/jshjohnson/Choices) along with Ajax to dynamically populate data into my select field from a database. However, I've encountered an issue when using the following code: const choices = new C ...

"The issue I'm facing with Next.js is that the fetched data is not displaying in the template. Additionally, I'm

I am encountering an issue with my API data where it is being called twice in the terminal. Additionally, I am trying to display this data on my page template but for some reason, it is not showing up. Here is the code snippet in question: Here is my code ...

The term "GAPI" has not been declared or defined within the Svelte

Encountering an issue while trying to incorporate the Youtube data API into my Svelte application. Upon loading the site, the error message displayed is: Uncaught ReferenceError: gapi is not defined Reviewing the relevant code reveals: <svelte:head> ...

Is there a way to flip a figure that is flipped upside down?

I'm currently working on creating a map using a json file to go from d3.js to Three.js. However, when the map is displayed, it appears upside down. I'm wondering if there is a way to flip it so that it displays correctly. As a newcomer to d3 and ...

AngularJS enables you to easily manipulate image width and height using the ng-file-upload feature

Seeking assistance with validating image width and height based on a 1:3 ratio prior to uploading using ng-file-upload. The validation should occur before sending the image to the server. Unsure how to retrieve the dimensions of the selected image for val ...

In WordPress, the magic_quotes feature is essential for json_decode to function properly

In my current project on the client side, I am dealing with an array of JavaScript objects. Upon submission, this array needs to be sent to PHP using a form and then further manipulated on the server-side. As I work on building or modifying the array of o ...