Implementing Java script closures for making asynchronous ajax requests

I am facing an issue with the data and JavaScript loops while using Ajax to fetch the data. The two loops are working fine with their respective values, but when I include Ajax inside the inner loop, the requests are not being executed in sequence. My requirement is to have the data fetched in the order of the loops. How can this be achieved?

var final = {};
final.reports = ['a','b','c']
final.clients = ['x','y']
final.reportDataJson = [];

for(var i=0;i<final.reports.length;i++){
        (function(i,reactthis){

            for(var j=0;j<final.clients.length;j++){
                (function(i,j,final){
                    console.log(i+" "+j+" "+final.clients[j])
                    // this shows correct i j values
                    $.ajax({
                        url: url,
                        cache: false,
                        success: function(html) {
                            var reportResponse = {
                                reportname : final.reports[i],
                                clientname : final.clients[j],
                                reporthtml : html,
                                reportgraph : ''
                            }
                            final.reportDataJson.push(reportResponse)
                            //console.log(i,j)
                            if( i == final.reports.length-1 && j == final.clients.length-1){

                                console.log(final.reportDataJson);

                            }
                        },
                        error: function(xhr, status, err) {
                            if( i == final.reports.length-1 && j == final.clients.length-1){
                            }
                        }
                    })              

                })
            }


        })(i,final);
    }

Answer №1

To harness the power of $.ajax, you can utilize its return value as a Promise and combine it with $.when to wait for multiple Promises and receive the resolved values sequentially!

var final = {};
final.reports = ['a', 'b', 'c'];
final.clients = ['x', 'y'];
final.reportDataJson = [];

$.when.apply($, [].concat.apply([], final.reports.map(function(report) {
    return final.clients.map(function(client) {
        return $.ajax({
            url: url,
            cache: false
        }).then(function(results) {
            var html = results[0];
            // results[0] is same as success: html argument
            // results[1] is textStatus
            // results[2] is jqXHR
            return {
                reportname: report,
                clientname: client,
                reporthtml: html,
                reportgraph: ''
            };
        });
    })
}))).then(function() {
    final.reportDataJson = [].slice.call(arguments);
    console.log(final.reportDataJson);
});

For using $.when.apply effectively, remember that $.when accepts promises as arguments 1 to n.

By utilizing [].concat.apply, you can "flatten" the array of arrays produced by the nested .map functions.

If you prefer working with native Promises, you can simplify the process like this:

Promise.all([].concat.apply([], final.reports.map(function(report) {
    // code unchanged from above ....
}))).then(function(results) {
    final.reportDataJson = results;
    console.log(final.reportDataJson);
});

With Promise.all, an array of promises is accepted, and the callback function in .then receives a single argument containing the results of those promises.

And if you want to embrace ES2015+ features:

Promise.all([].concat.apply([], final.reports.map(report => final.clients.map(client => $.ajax({
    url: url,
    cache: false
}).then(([html, status, jqXHR]) => ({
    reportname: report,
    clientname: client,
    reporthtml: html,
    reportgraph: ''
})))))).then(results => console.log(final.reportDataJson = results));

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

When the Jqueryui dialog is closed, it effectively terminates the current JavaScript thread

Hello there, I'm currently facing an issue with closing my jQuery dialog box. The situation involves a comet connection that sends messages to my browser. My goal is to perform certain actions upon receiving a message, close the dialog, and then conti ...

Cease processing ajax requests on the server side

After conducting thorough research on the topic of canceling ajax requests, I have come across several threads discussing this matter. One particular thread caught my attention: Abort Ajax requests using jQuery The post explains how when you use the abor ...

Is it possible to swap out one ID value for another using JavaScript?

I am facing two issues 1) First Issue I need to update the current id value with a new one. Whenever the a tag is clicked, an event in jQuery code should be triggered to change the id value. For example, When a button is clicked <div class="video" i ...

Learn the best practices for incorporating jQuery and other JavaScript libraries in your Angular2 projects

Is it possible to integrate a demo showcasing Bootstrap carousel with CSS3 animations in Angular2 using HTML, CSS, and JS? I have created my own implementation in Plunker with Angular2, but I am facing issues with the animated inner content of the carousel ...

Ensuring the length of an array meets security requirements in Firebase rules

Can the votes array be restricted to exactly 5 entries? Checking if newData.child('votes').val().length === 5) doesn't work because the length property only applies to strings. Here is a sample of my data: votes $voteID page:"12345 ...

Switch between showing and hiding a div by clicking on an image

Currently, I am experimenting with the toggle div function and utilizing images as triggers for toggling. For instance, when a div is closed, an image of a "plus" sign indicates to the user that it can be expanded, and vice versa for compressing the div. T ...

In React, the constant always has a default value of "Object : Default"

My current project involves using SlateJS and I am encountering an issue when trying to load data into a const using: imgData = data.get("file"); Everything works as expected if React is not imported, but once it is included, the object contains unexpecte ...

Pass information to a PHP file using JavaScript when the form is submitted

Essentially, I am looking to extract values from various inputs and spans using JavaScript when the submit input is clicked. These values will then be sent to PHP using $post in order to ultimately send them via email. Previously, I tested replacing all of ...

ERROR: Issue detected in the e class under the e_Host - inline template 0:0

As I was upgrading my angular2 project to RC5, a major issue surfaced. Despite reducing all the code to its minimum in order to debug the problem, I couldn't pinpoint its origin. Every request made by my app led to the following error message (as seen ...

Switch the class of the child element from the previous element using jQuery

I'm attempting to create a toggle effect on click that switches a class (font awesome) like this: $( ".expandTrigger" ).click(function() { $( ".expand" ).first().toggle( "fast", function() {}); if ( $( this ).prev().child().is( ".fa-plus-cir ...

Utilizing AngularJS: Triggering a controller function from a directive

I am currently working on a project with a model named 'user', which includes a controller called 'login' and a directive called 'userMenu'. My goal is to have the userMenu directive utilize the 'login' controller th ...

Wait for the page to finish loading using C# and .NET Webclient

I'm attempting to load the HTML of a page using Ajax, but there is an issue with Webclient.Downloadstring() returning too quickly. This results in the Ajax page not loading completely, thus I am not receiving the correct HTML content. Is there a way ...

Learn how to effectively utilize templateURL in an express and angular project

Our project utilizes Express without any view engine. To set up static directories, we have the following: app.use(express.static(__dirname + '/public')); app.use(express.static(__dirname + '/view')); app.use(express.static(__dirname + ...

Add and remove input fields in real-time while also modifying nested arrays dynamically

Is it possible to dynamically add new input fields to an object within a nested array in React JS when the user clicks on a plus sign? I am looking to dynamically add and remove inputs. I am interested in adding and deleting propositionTimes dynamically u ...

The component fails to update even after changes are made to the Redux state

I currently have 4 buttons, each with a different color, and I want to display the last 10 button clicks as colors on 10 squares. The redux state is being used to map and display the square colors, which are also stored in localStorage. When a button is c ...

Injecting windows in Angular

Is there a way to prevent the Angular instance from injecting into the global (window) scope when required and bundled with webpack or any other module bundler? Upon inspection, I discovered that the current main Javascript file in the Angular npm package ...

Invoke the ng-click function within the ng-change function

Just starting out with angularjs and I have a question. I am currently using single select and I want to retrieve the value selected and based on that value, perform an action. For example, if the value is "DELETE" then I would like to trigger the ng-clic ...

Retrieve data from various arrays

I am currently using the Adobe Echosign API to structure some data in a table. Here is how the output appears: { "agreementId": "", "events": [ { "actingUserEmail": "", "actingUserIpAddress": "", "date": "date", "descriptio ...

Sorting items in backbone.js can be achieved by using the sortBy method

Currently, I am delving into learning backbone.js and have decided to create my own Todo application using backbone.js along with a local storage plugin. At this point, I have successfully developed the Todo app where you can add and remove tasks. However, ...

Prevent rapid event triggers with a jQuery slider

I am currently working with an event function in JavaScript that involves a slider and a tooltip element. Here is the code snippet: //Hide the Tooltip initially tooltip.hide(); //Initialize the Slider slider.slider({ ...