简体   繁体   中英

Calling javascript-function inside a foreach-loop, wait for reply?

I'm a little puzzled on how to solve this. I have a function updateDate( id ) that updates a specific row in the database with the ID passed along. This function makes an AJAX-call to a PHP-script and it takes a bit of time to run.

I then have this other function called updateDates() which makes an AJAX-call to another PHP-script to get all ID's that needs updating, then loops through these and calls updateDate( id ) with the current ID in the loop.

The problem is that the loop doesn't seem to wait for a response from updateDate( id ) before continuing the loop so it creates like 2398572375 AJAX-calls at the same time and it bugs out.

How can I make the loop wait for a response from updateDate( id ) before continuing?

updateDate( id ) returns true when readyState of the AJAX-call is 4(meaning when the response is done) and I tried in the loop to do:

if( updateDate( id ) ) { Do something. }

Didn't help. Any ideas about this?

EDIT: Here's some of the code as requested.

updateDates():

                function updateDates()
                {

                    ids = new XMLHttpRequest();

                    ids.open( "GET", "<?php echo anchor("index.php/main/ajax/getIdsToUpdate"); ?>", true );
                    ids.onreadystatechange = function() {

                        if( ids.readyState == 4 )
                        {

                            var response = $.evalJSON( ids.responseText );
                            if( response.type == 1 )
                            {

                                $.each( response.message, function( index, value ) {

                                    if( value != '' )
                                    {

                                        if( updateDate( value ) )
                                            alert('Checked: ' + value);

                                    }

                                });

                            }

                        }

                    }

                    ids.send(null);

                }

updateDate( id ):

                function updateDate( id )
                {

                    req = new XMLHttpRequest();
                    req.open("GET", "<?php echo anchor("index.php/main/ajax/updateDate/"); ?>" + id, true);

                    req.onreadystatechange = function() {

                        if( req.readyState == 4 ) 
                        {

                            var value = $.evalJSON( req.responseText );

                            // Updating a DIV on the site..

                            return true;

                        }

                    }
                    req.send(null);

                }

You didn't show much of your code or what you're using to make ajax calls, but you can do something like this pseudo code where you kick of the next ajax call upon the success of the previous one:

var idArray = [];   // suppose this is an array of ids that you want to update with individual ajax calls.

function updateNextId(list, index) {
    if (index < (list.length -  1)) {
        ++index;
        var id = idArray[index]
        ajax(parmss, function() {
            // success handler
            updateNextId(list, index);
        });
    }
}

A better solution would be to send all the IDs in one ajax call and have the server just deal with multiple IDs.

I think the trick is to define a callback that gets called when the AJAX function completes, then call the updateDates function recursively from there.

In pseudo-code:

function updateDates(items) {
    current_id = items[0];
    updateDate(current_id, oncomplete: function() {
        next_items = everything_but_current_item(items, current_id)
        updateDates(next_items)
    });
}

you may get a stack overflow after a certain amount of recursion, but this is the simplest way to implement I'm thinking.

Try using the jQuery looping method .each() , jQuery $.ajax() and a callback function:

$('your element selection').each(function(){
  var thisElement=this;
  $.ajax(url,{
    success:function(data, textStatus, jqXHR){
      //do something to 'thisElement' element with 'data'
    } 
  });
});

I agree with the previous poster that a single AJAX call with multiple IDs is better.

There are 2 good ways to do this without compromising with a synchronous (and locked) UI.

A. Create a batch update PHP script

This one's easy enough. Extend your PHP script so that it can take a list of IDs and dates instead of just one at a time. This is the most performant and best solution.

B. Convert to a queue

You should convert updateDates() into a dequeuing function. Here's what that means:

Every time updateDates() is called, it pops the first element off the array of IDs you need to update, calls the ajax function, and then sets updateDates as the callback from the Ajax call.

Pseudocode/rough sketch:

function updateDates() {
    if(allDates.length == 0) return;

    var data = allDates.unshift();
    $.post('/save.php', { 'id': data.id, 'date': data.date }, updateDates);
}

AJAX stands for Asynchronous Javascript and XML. That means it doesn't wait for a response before continuing. If you want it to wait before continuing, make it synchronous instead.

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