简体   繁体   中英

Executing unknown number of parallel ajax calls based on data returned by a previous ajax call

I have a built a php backend which returns a JSON object (effectively a 2D array, I can reference it as json[0][0] for example, I don't know why though, I did not parse the JSON object) of information(train number, days it runs on etc) on trains between two stations.

Now what I want to query the availability of each train. I already have the php script for that (which returns a JSON object as well, giving the availability of the specified date as well as the next 5 days.).

This availability php script requires some input which is present as the first element of every nested(wrong term to use ?) array eg : json[0][0], json[1][0], json[2][0] if 3 trains are returned

I want this information returned as a response to parallel ajax calls. In the end I want to create a table based on these responses. My problems are:

  1. Since I don't know the number of trains which will returned before hand, hence the number of parallel ajax calls to be made, how do I code this portion ?
  2. Best way to make parallel calls seems to be $.when, how do I use it in this problems ?

I have just begun coding the function, and have something like this, yes I am an utter novice with JS and jQuery :

$(document).ready(function() {
$("form").submit(function(){    
    event.preventDefault();

    $.ajax({
      //type: "POST",
      url: "./trains_bw_stations.php",
      dataType: 'json',
      data: { source: $('input[name*="src"]').val(), destination: $('input[name*="dstn"]').val(), 
                day: $('input[name*="day"]').val(), month: $('input[name*="month"]').val(), cl: $('input[name*="cl"]').val()  }
    })
      .done(function(trains) {
        console.log(trains)
        var requests = [], allData = {};

        for (var i = 0; i < trains.length; i++) {
            console.log(trains[i][0]);
            requests.push($.ajax({
                url: './availability.php', 
                dataType: 'json',
                data: { 
                        day: $('input[name*="day"]').val(), month: $('input[name*="month"]').val(),lccp_trndtl: trains[i][0]  }
                // success: function(data) {
                //  console.log(data);
                //     allData[''+i] = data;

            }).done(function(data) {
                    console.log(data);
                    allData[i] = data})
            );
        }

        $.when.apply(requests).then(function() {

            console.log(allData) // this is line 41

            }
            // all requests have completed
            // allData array now contains the data from all the requests
            // put your processing logic in here...
        });
    });
    });
    });

allData remains empty ! console output :

XHR finished loading: GET "http://localhost/irl_poster/trains_bw_stations.php?source=ndls&destination=hyb&day=7&month=8&cl=SL". jquery-2.1.1.min.js:4
[Array[15], Array[15], Array[15]]
 ajaxRequests.js:19
12650NZM KCG YYYNYNYYA ajaxRequests.js:23
12724NDLSHYB YYYYYYYYA ajaxRequests.js:23
12722NZM HYB NYYYYYYYA ajaxRequests.js:23
Object {} ajaxRequests.js:41
XHR finished loading: GET "http://localhost/irl_poster/availability.php?day=7&month=8&lccp_trndtl=12650NZM+KCG+YYYNYNYYA". jquery-2.1.1.min.js:4
Object {0: Array[4], 2: Array[4], 4: Array[4], 6: Array[4], 8: Array[4], 10: Array[4]}
 ajaxRequests.js:34
XHR finished loading: GET "http://localhost/irl_poster/availability.php?day=7&month=8&lccp_trndtl=12724NDLSHYB+YYYYYYYYA". jquery-2.1.1.min.js:4
Object {0: Array[4], 2: Array[4], 4: Array[4], 6: Array[4], 8: Array[4], 10: Array[4]}
 ajaxRequests.js:34
XHR finished loading: GET "http://localhost/irl_poster/availability.php?day=7&month=8&lccp_trndtl=12722NZM+HYB+NYYYYYYYA". jquery-2.1.1.min.js:4
Object {0: Array[4], 2: Array[4], 4: Array[4], 6: Array[4], 8: Array[4], 10: Array[4]}

You have an error in your $.when.apply call - it needs an initial context parameter, typically $

Your code also suffers the common problem of using the loop variable i from inside an asynchronous callback at which point it no longer retains its original value and the results all end up in allData[trains.length + 1]

So, instead of trying to accumulate allData[i] in the .done callback you can remove that .done call altogether, and then within the .when().then() callback you can use the arguments array to access the individual results, which will automatically appear in the correct order:

$.when.apply($, requests).then(function() {

    // convert the arguments array, where each argument is in the form
    // [data, textStatus, jqXHR], into an array of just the data values
    var allData = [].map.call(arguments, function(arg) {
        return arg[0];
    });

    ...
});

The initial request loop can also be slightly simplified using Array.prototype.map :

var requests = trains.map(function(train) {
    // no "i" variable needed - use "train" instead of "train[i]"
    return $.ajax({
        ...
    });
});

You are correct that you need to use $.when , although your syntax is a little off. Try this:

.done(function(json) {
    var requests = [], allData = [];

    // loop over your result, amend as needed
    for (var i = 0; i < json.length; i++) {
        requests.push($.ajax({
            url: 'foo.html', // build as needed using properties of json
            success: function(data) {
                allData.push(data);
            }
        }));
    }

    $.when.apply(requests).then(function() {
        // all requests have completed
        // allData array now contains the data from all the requests
        // put your processing logic in here...
    });
});

If you need to maintain the order of the data received, you could change the allData variable to an object, keyed by the index of the loop:

// note: amended lines only
var requests = [], allData = {};

success: function(data) {
    allData[i] = data;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM