Последовательный вызов функций JS

#javascript #jquery #arrays #post

#javascript #jquery #массивы #Публикация

Вопрос:

Вот что я пытаюсь сделать (фактическая проблема другая, но обзор ее следующий):

  1. У меня есть массив [A .. Z].
  2. Для каждого алфавита из приведенного выше массива у меня есть другой массив в виде:

     someArray[alphabet] = [1..100] //another array
      
  3. Для каждого числа в someArray[алфавит] существует еще один массив:

     anotherArray[number] = [a..z,A..Z,1..1000]
      

Предположим, что для каждого алфавита я извлекаю someArray[алфавит], и для каждого числа в someArray[алфавит] я извлекаю anotherArray[число], все с сервера — это требует времени.

Кроме того, функции для их получения следующие — я выполняю вызовы jQuery post для получения данных с сервера. Мне нужно выполнить их по порядку.

 getAlphabets()
{
    //I get them here
    //For Each alpha, I call:
    getNumbers(alpha);
}
getNumbers(alpha)
{
    //I get someArray here.
    //For Each element in someArray
    //getAnotherArray(element)
}
getAnotherArray(number)
{
    //I get them here
    //For Each element in anotherArray
    //get all [a..z,A..Z,1..1000]
    //display them
}
  

Проблема заключается в том, что итерация getNumbers (alpha) не ожидает завершения getAnotherArray(previousIteration). Выполнения (вызовы функций выполняются параллельно (одновременные выполнения для A .. Z) и никак иначе.

Мои шаги:

  1. Я могу извлечь все данные, как ожидалось, но не последовательно.

  2. Я пытался использовать флаги и setInterval, clearInterval, чтобы разрешить / запретить следующие итерации — они работают не так, как ожидалось.

  3. Я также пытался использовать что-то вроде — getAlphabets() amp;amp; getNumbers() amp; getAnotherArray(), думая, что это будет выполняться последовательно, но я ошибался.

Комментарии:

1. Вам обязательно выполнять отдельный вызов ajax для каждой отдельной ячейки в вашем 3D-массиве, и вы хотите, чтобы они выполнялись последовательно? Эти массивы уже существуют, и вы просто хотите выполнить итерацию по ним, выполняя вызов ajax для каждой ячейки? Или вы создаете массивы по мере выполнения вызовов ajax?

2. Я создаю массивы с помощью вызовов ajax. Сначала я получаю список алфавитов. Затем для каждого алфавита я вызываю getNumbers(), и для каждого числа в массиве, возвращаемом getNumbers(), я вызываю getAnotherArray() -> Он передает соответствующие параметры, получает соответствующие элементы и строит массив из этого. Я могу выполнять их все сразу, но мне нужно, чтобы они были последовательными.

Ответ №1:

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

Вот пример:

Предположим, у вас есть массив произвольной длины:

 var theData = [...];
  

И вы хотите выполнить вызов ajax для каждого элемента в этом массиве и собрать результаты в другой массив. По определенной причине вы хотите принудительно выполнять вызовы Ajax последовательно, чтобы второй вызов выполнялся только после завершения первого вызова и так далее.

 function processArray(data) {
    var def = $.Deferred();
    var currentItem = 0;
    var results = [];

    function next() {
        if (currentItem < data.length) {
            $.ajax(...).done(function(result) {
                // process the result here
                results.push(result);
                // advance the counter and start the next Ajax call
                  currentItem;
                next();
            }).fail(function(jqXHR, textStatus, errorThrown) {
                def.reject(jqXHR, textStatus, errorThrown);
            });
        } else {
             def.resolve(results);
        }
    }
    next();
    return def.promise();
}

// call it like this
processArray(theData).done(function(results) {
    // do something with the results array here
});
  

Теперь, если у вас есть три измерения состояния итерации, то отслеживание состояния становится немного сложнее (у вас было бы три версии CurrentItem, чтобы отслеживать, где вы находитесь в каждом из трех измерений), но в противном случае это могла бы быть аналогичная логика с дополнительным усложнением: когда вы заканчиваете одно измерение, вам нужно перейти к следующей строке и начать снова.

Комментарии:

1. Спасибо за обновление. Пожалуйста, дайте мне немного времени, чтобы разобраться в коде.

Ответ №2:

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

 async: false
  

асинхронный (по умолчанию: true)
Тип: логическое значение
По умолчанию все запросы отправляются асинхронно (т.Е. по умолчанию установлено значение true). Если вам нужны синхронные запросы, установите для этого параметра значение false. Междоменные запросы и запросы типа данных «jsonp» не поддерживают синхронную работу. Обратите внимание, что синхронные запросы могут временно блокировать браузер, отключая любые действия, пока запрос активен.

Пример :

 jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });
  

Комментарии:

1. Никогда не рекомендуется использовать async: false с вызовами ajax, поскольку это просто блокирует браузер. Решение состоит в том, чтобы закодировать итерацию другим способом, который работает с асинхронными вызовами, а не избавляться от асинхронных вызовов.