What is the best way to execute ajax for a collection of objects?

I'm grappling with the effectiveness of my ajax implementation as I cycle through an array of data using a for loop:

loadProfiles.js

var tempString = "";
var searchPeople = function(sv){
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function(){
        if(xhttp.readyState == 4 && xhttp.status == 200){
            tempString = xhttp.responseText;
            loadPeople(tempString, sv);
        }
    }

    var searchvalue = sv;
    searchvalue = searchvalue.join(" ");

    xhttp.open("GET", "php/searchProfiles.php?searchvalue=" + searchvalue, true);
    xhttp.send();
}

var loadPeople = function(people, sv){
    loadedPeople = [];
    var normList = people.split(",");
    var list = people.toLowerCase().split(",");
    list.splice(list.length - 1, 1);
    var zsearch = sv;
    for(var i = 0; i < list.length; i++){
        loadedImageId[i] = list[i].split("_")[1];
        if(loadedImageId[i] == 0){
            loadedImageId[i] = "images/GrayProfilePic.png";
        }
        else{///////////////////////////////////This is what I need to fix
            var grabPic = new XMLHttpRequest();
            grabPic.onreadystatechange = function(){
                if(grabPic.readyState == 4 && grabPic.status == 200){
                    console.log("ready to go");
                    loadedImageId[i] = grabPic.responseText;
                    if(loadedImageId[i] == "Error1"){
                        loadedImageId[i] = "images/GrayProfilePic.png";
                    }
                }
            }

            grabPic.open("GET", "php/grabProfPics.php?imageid=" + loadedImageId[i], true);
            grabPic.send();
        }//////////////////////////////////////////////
        list[i] = list[i].split("_")[0];
        for(var j = 0; j < zsearch.length; j++){
            if(list[i].indexOf(zsearch[j]) > -1){
                if(loadedPeople.indexOf(list[i]) == -1){
                    if(loadedPeople.indexOf(normList[i].split("_")[0]) == -1){
                        loadedPeople.push(normList[i].split("_")[0]);
                    }
                }
            }
        }
    }
    console.log(loadedPeople);
    console.log(loadedImageId);

}

searchProfiles.php

$query = "SELECT username, imageid FROM `memberHandler`";
    $result = mysqli_query($connect, $query) or die("Could not query");
    while($row = mysqli_fetch_assoc($result)){
        echo $row['username'] . "_" . $row['imageid'] . ",";
    }

grabProfPics.php

$query = "SELECT image, mime_type FROM memberProfilePictures WHERE `id`='$imageid'";
    $result = mysqli_query($connect, $query);
    if(mysqli_num_rows($result) != 0){
        $row = mysqli_fetch_assoc($result);

        $imagesrc = $row['image'];
        $imagesrc = base64_encode($imagesrc);
        $imagetype = $row['mime_type'];

        echo "data:" . $imagetype . ";base64," . $imagesrc . "";
    }
    else{
        echo "Error1";
    }

One issue I'm facing is that the server's response time can cause the for loop iteration variable 'i' to be different by the time the callback is executed. Is there a more efficient way to handle this and dynamically update the array based on its current value? Thank you for any insights =)

In essence, I'm attempting to iterate over image IDs and if it's non-zero (indicating they have a profile image set), then making an ajax request to fetch the corresponding image from a database. Subsequently, updating the array with the retrieved image source. Apologies for any earlier ambiguity in my explanation.

Answer №1

Update on Original Post: I initially provided this response without seeing your complete code pasted in. While my advice still holds, here are some additional thoughts to consider:

  • It appears that you are directly inserting data into SQL query strings. Although it may make "Little Bobby Tables" proud (reference: XKCD comic), you should take precautions against SQL injection.
  • If you prefer writing the standard new XMLHttpRequest(); code yourself instead of utilizing a library like fetch or jQuery, consider encapsulating it within a function that handles URL, data, method, success callback, and error callback parameters. Utilizing libraries can simplify and optimize your code.
  • In the specific error segment you highlighted, the issue lies with the outdated value of i, which no longer aligns with the index used in the corresponding call.

The sense of asynchronicity explained:

Asynchronous Nature

You touch upon managing asynchronous tasks, such as AJAX calls, in your discussion.

Various approaches exist for addressing this challenge, including the use of callbacks and promises.

While synchronous processing is feasible, favoring asynchronous operations, particularly for substantial applications, proves beneficial.

Illustrative Example

Let's define a hypothetical service. Though in this instance it remains locally hosted, the underlying concept holds true. You input a parameter (e.g., profile ID) and receive an output (profile image URL).

// After ~1-2 seconds, determine if the input number is even or odd
var checkEvennessAsync = function(num, cb) {
  setTimeout(function(){
    var isEven = num % 2 === 0;
    cb(num + " is " + (isEven ? "Even" : "Odd"));
  },(Math.floor(Math.random() * 12) + 3) * 150);
};

Although diverse signature formats exist, the essence remains consistent — entering data triggers a brief delay followed by a response.

For instance:

checkEvennessAsync(2,console.log);
checkEvennessAsync(3,console.log);
checkEvennessAsync(7,console.log);

This sequence could yield:

"7 is Odd"
"2 is Even"
"3 is Odd"

Here's our test dataset:

var infoBatch = [
  10,11,12,
];

To dispatch our data to the service and fetch results accordingly, we can employ a simple iterator loop approach (Note: This serves demonstration purposes only. Real-world scenarios often warrant reliance on promises).

var retrieveInfoResponses = function(infoBatch, cb) {
  var responsesCollection = [];
  infoBatch.forEach(function(i){
    checkEvennessAsync(i,function(response){
      console.log("Assessment for " + i + ": " + response);
      responsesCollection.push({num:i,response:response});
      if (responsesCollection.length >= infoBatch.length){
        cb(responsesCollection);
      }
    });
  });
};

Note that the encompassing function for all asynchronous calls operates asynchronously itself (under the callback mechanism), necessitating a 'done' callback.

Expanding on this:

Upon initializing a container array for result accumulation, iterate through each data item within the information array:

var responsesCollection = [];
infoBatch.forEach(function(i){

For every element, initiate an asynchronous request.

checkEvennessAsync(i,function(response){

Demonstrate the receipt of data from the extended operation for every element alongside their console outputs, storing both the outcomes and original data inside the responses collection. Maintaining source data proves vital in certain cases (e.g., correlating profile IDs with respective URLs) where order retention may not hold merit given the inherent unpredictability of async calls.

console.log("Feedback for " + i + ": " + response);
responsesCollection.push({num:i,response:response});

Subsequently, examine parity between received responses and issued requests. If equality stands unachieved, signifying pending results, halt the process. Conversely, if correspondence prevails, invoke the primary callback and convey the comprehensive dataset back to the initiating party.

if (responsesCollection.length >= infoBatch.length){
  cb(responsesCollection);
}

An invocation such as:

retrieveInfoResponses(infoBatch,console.log);

could return outcomes along these lines:

"Analysis for 10: 10 is Even"
"Analysis for 12: 12 is Even"
"Analysis for 11: 11 is Odd"
[[object Object] {
  num: 10,
  response: "10 is Even"
}, [object Object] {
  num: 12,
  response: "12 is Even"
}, [object Object] {
  num: 11,
  response: "11 is Odd"
}]

Promising Future

This model concentrates solely on exploring handling methods for asynchronous actions and does not address nuanced production considerations such as error mitigation since Ajax calls possess intrinsic failure potential.

Conventionally emphasized by CallMeNorm, delving into the realm of promises presents significant advancement possibilities albeit requiring separate dedicated discourse.

Answer №2

The current example provided will likely result in errors.

information[i] does not include a method called doAjaxstuff. However, achieving what you are aiming for can be easily accomplished using Promises which are now supported in modern browsers and even jQuery 3.0 has an implementation that is compliant. In this scenario, you could implement the following code:

var promises = information.map(function(data, idx) {
    // The doAjaxstuff function should return a promise
    return Promise.resolve([idx, doAjaxstuff(data)]);
});

var orderedPromises = promises.reduce(function(acc, val) {
        return acc[val[0], val[1]];
    }, []);
});

Promise.all(orderedPromises)
.then(function(result) {
   // Implement your functionality here
});

Answer №3

When making Ajax calls, it's important to remember that they are asynchronous in nature, meaning they will not wait for other processes like a for loop to finish before continuing. If you need the iteration to pause and only resume once the ajax call returns, you must set it to be synchronous.

To achieve this, simply include async: false

For further details, refer to the jquery documentation

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

What is the best way to incorporate two range sliders on a single webpage?

I recently started using rangeslider.js on my webpage. I wanted to convert two input fields into range sliders, so I began by converting one successfully. Initially, the HTML code looked like this: <div class="rangeslider-wrap"> <input type=" ...

Best practices for securely storing access tokens in React's memory

I'm on a quest to find a secure and efficient way to store my access token in a React application. First and foremost, I have ruled out using local storage. I don't see the need to persist the access token since I can easily refresh it when nece ...

`Firefoxx border table glitch`

When attempting to open/close tables in Firefox using this link, unnecessary borders appear. https://i.sstatic.net/4tQCE.gif One way to fix this issue is by implementing the following JS solution: setTimeout(function () { $table.css({'table-la ...

Invoke a bounded function within an Angular directive using the ng-click event

I was wondering if it's possible to invoke a bound function within a directive by clicking on a specific part of a div. Currently, I have a div with an inner div that acts as a button for expanding the main div. The larger div has a directive associat ...

Express routes are malfunctioning

I have a situation with two different routes: /emails and /eamils/:id: function createRouter() { let router = express.Router(); router.route('/emails/:id').get((req, res) => { console.log('Route for get /emails/id'); }); ...

Problem encountered while retrieving data

I am currently working on a website that connects vendors and clients, where clients can order services from various vendors. In my database, I have a table named "orders" which stores all the details of orders such as client email, vendor email, and orde ...

the correct data format for posting using axios

I am looking to use axios for posting data in a specific format using jQuery's ajax post method. https://i.stack.imgur.com/SwKuS.jpg var data = {}; data.params = querystring.stringify({'cmd': 'getUnreadCount', 'isNewAdmin&ap ...

In Javascript, use the replace() function to target and replace text that is not contained

Seeking help with highlighting search strings in an autocomplete form. In my current approach, I aim to encapsulate the search term within specific tags for emphasis. However, complications arise when the pattern resides within HTML tags. var searchPatter ...

Utilizing the W3Schools CodeColor library across various elements

Looking to provide code examples using a JS code highlighter with an ID? Check out this URL for a demonstration: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_syntax_highlight Want to use this for multiple examples but finding that the ID only ...

Utilizing AJAX to Invoke a Method in a CS Page: A Step-By-

I am trying to utilize AJAX to call a method in my CS page. Below is the design code I am using: <!-- Name --> <input type="text" name="name" id="name" required="required" class="form" placeholder="Name" /> <!-- Email --> <input type= ...

Slick slider issue: Unexpected TypeError - the slick method is undefined for o[i]

I'm facing an issue where, upon clicking the search button, I want the previous search results to clear and new ones to be displayed. However, this action triggers a slick slider error, causing all items to align vertically instead of in the intended ...

When updating items in a FormView, the Dropdownlist may still hold the previous values

In a formview, there are two dropdownlists - one for cities and one for states. Whenever the state dropdownlist is changed, the city dropdownlist gets updated using javascript. If the city dropdownlist remains unchanged via javascript, the values of dlCi ...

What is the process of retrieving user input from an HTML form and locating specific data within it?

Here is the structure of my form: <div id="employeeinfo" style="padding:40px" class="employee-body"> <form id="employeeform" title="" method="post"> <label class="title">First Name</label> < ...

Searching and selecting columns in React using Material-UI

Currently, I am using Material-UI data tables and have implemented a search functionality similar to this Codesandbox example, which only searches the Name/Food column. This is my existing code snippet: const [filterFn, setFilterFn] = useState({ fn: items ...

Verification of unique custom string

How can I ensure that a string follows the specific format of x.xx.xxxxx? The first character is mandatory, followed by a period, then two characters, another period, and finally any number of characters of varying lengths. ...

Exploring the passing of parameters in Angular JS getters

In my Angular 1.6.x project, I have a collection of checkboxes that store their state in a variable called selectedJobIds. This variable contains the ids of selected jobs along with their corresponding true or false values: $scope.selectedJobIds = { 23: ...

What's the best way to create an onclick event for a li element that includes a pseudo-element ::before

I have successfully created a Timeline using HTML and CSS elements. The visual result is as follows: My goal is to enable users to click on the second circle, triggering a color change in the line that connects the first and second circles. This color tra ...

Sending an AJAX request from JavaScript to a user control in ASP.NET

JavaScript Function: function CreateProposal(GetProposal, ProductName, ProductID) { $.ajax({ type: "POST", url: "Page.ascx/Proposal", data: JSON.stringify({ GetProposal: GetProposal, ProductName: ProductName, ProductID: ProductID ...

Deciphering the ins and outs of the jQuery each function - Surprising

I'm currently trying to understand how the each function works. In this specific scenario demonstrated in this fiddle here, my goal is to iterate through the selected elements of a list box individually. Initially, I anticipated an output like this: ...

Updating the state of a parent component from a slot in VueJS

Hi there, I am currently facing a challenge as a newcomer to Vue. Within my project, I am using Vuetify and have a v-dialog component with a slot structured as follows: <template> <v-row> <v-dialog v-model="dialog" max-width="600px"&g ...