Вызов функции javascript внутри цикла foreach, ждать ответа? - PullRequest
0 голосов
/ 17 сентября 2011

Я немного озадачен тем, как решить эту проблему. У меня есть функция updateDate (id), которая обновляет определенную строку в базе данных с помощью переданного идентификатора. Эта функция делает AJAX-вызов PHP-скрипта, и для ее запуска требуется немного времени.

Затем у меня есть другая функция updateDates (), которая выполняет AJAX-вызов другого PHP-скрипта для получения всех идентификаторов, требующих обновления, затем выполняет их цикл и вызывает updateDate (id) с текущим идентификатором в цикле.

Проблема в том, что цикл не ожидает ответа от updateDate (id) перед продолжением цикла, поэтому он создает как 2398572375 AJAX-вызовы одновременно и выдает ошибку.

Как я могу заставить цикл ждать ответ от updateDate (id), прежде чем продолжить?

updateDate (id) возвращает true, когда readyState AJAX-вызова равен 4 (имеется в виду, когда ответ сделан), и я попытался в цикле сделать:

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

Не помогло. Есть идеи по этому поводу?

РЕДАКТИРОВАТЬ: Вот часть кода в соответствии с просьбой.

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);

                }

Ответы [ 5 ]

2 голосов
/ 17 сентября 2011

Вы не показали большую часть своего кода или того, что вы используете для выполнения вызовов ajax, но вы можете сделать что-то вроде этого псевдокода, когда вы нажимаете следующий вызов ajax после успешного завершения предыдущего: *

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);
        });
    }
}

Лучшим решением было бы отправить все идентификаторы за один вызов ajax, и сервер просто справился с несколькими идентификаторами.

1 голос
/ 17 сентября 2011

Есть 2 хороших способа сделать это без ущерба для синхронного (и заблокированного) интерфейса.

A.Создать пакетный скрипт PHP

Это достаточно просто.Расширьте свой PHP-скрипт, чтобы он мог принимать список идентификаторов и дат, а не только по одному за раз.Это самое эффективное и лучшее решение.

B.Преобразовать в очередь

Вы должны преобразовать updateDates () в функцию удаления из очереди.Вот что это значит:

Каждый раз, когда вызывается updateDates (), он извлекает первый элемент из массива идентификаторов, которые необходимо обновить, вызывает функцию ajax, а затем устанавливает updateDates в качестве обратного вызова из вызова Ajax.

Псевдокод / ​​набросок:

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

    var data = allDates.unshift();
    $.post('/save.php', { 'id': data.id, 'date': data.date }, updateDates);
}
1 голос
/ 17 сентября 2011

Попробуйте использовать метод зацикливания jQuery .each(), jQuery $.ajax() и функцию обратного вызова:

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

Я согласен с предыдущим постером, что лучше один вызов AJAX с несколькими идентификаторами.

1 голос
/ 17 сентября 2011

Я думаю, что хитрость заключается в том, чтобы определить обратный вызов, который вызывается после завершения функции AJAX, а затем рекурсивно вызвать функцию updateDates.

В псевдокоде:

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

вы можете получить переполнение стека после некоторой рекурсии, но я думаю, что это самый простой способ реализации.

0 голосов
/ 17 сентября 2011

AJAX означает Асинхронный Javascript и XML. Это означает, что он не ждет ответа, прежде чем продолжить. Если вы хотите подождать, прежде чем продолжить, установите вместо этого синхронный .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...