Отправка одного AJAX-запроса за раз из цикла - PullRequest
10 голосов
/ 21 февраля 2011

Я знаю, что этот вопрос задавали бесчисленное количество раз, но я не могу понять, как заставить этот ответ работать в моем случае: дождаться, пока асинхронная функция JavaScript вернет

Я перебираю некоторые «телеканалы» во внешней петле, а затем перебираю даты на неделе во внутренней петле.Во внутреннем цикле я делаю ajax-запрос к серверу для извлечения данных, а затем сохраняю / кеширую его для последующего использования, вот так

var dates = []; //<-- Contains a list of dates for the coming week 
var baseUrl = "http://www.someserver.com";
var storedChannels = [1,2,3,4,5,6,7,8,9,10,45,23,56,34,23,67,23,567,234,67,345,465,67,34];

for(ch = 0; ch < storedChannels.length; ch++) {   
    var channel = storedChannels[ch];
    for(d=0; d < 7; d++) {
        var currentDate = dates[d];
        ajax({    
            url: baseUrl+"?ch="+channel+"&dt=currentDate"+,
            complete: function(res) {
                CMLocalStore.setString('ch' + ch + "_" + scheduleDay, res);
            },
        });
        //Want to wait here till the ajax request completes.
        //Do not want to continue to next iteration.
        //Do not want to fire of 50 bazillion ajax requests all at once
        //Why? Very limited bandwidth scenario, plenty of channels  
    }
}

PS: НЕТ JQuery, пожалуйста!Только простые решения JS

Большое спасибо!

Ответы [ 5 ]

18 голосов
/ 21 февраля 2011

Вы хотите что-то вроде этого. Я не проверял это, но надеюсь, вы поймете идею.

var dates = []; //<-- Contains a list of dates for the coming week 
var baseUrl = "http://www.someserver.com";
var storedChannels = [1,2,3,4,5,6,7,8,9,10,45,23,56,34,23,67,23,567,234,67,345,465,67,34];

function ProcessNext(ch, d) {
    if (d < 7) {
        d++;
    } else {
        d=0;
        if (ch < storedChannels.length) {
            ch++;
        } else {
            return;
        }
    }

    var channel = storedChannels[ch];
    var currentDate = dates[d];
    ajax({    
        url: baseUrl+"?ch="+channel+"&dt=currentDate"+,
        complete: function(res) {
            CMLocalStore.setString('ch' + ch + "_" + scheduleDay, res);
            ProcessNext(ch, d);
            },
    });
}

ProcessNext(0, 0);
4 голосов
/ 21 февраля 2011

Вам необходимо превратить ваш цикл в цепочку обратных вызовов.

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

1 голос
/ 23 февраля 2011

По сути, ответ заключается в использовании рекурсивных вызовов вместо использования циклов.Просто хотел добавить этот ответ для тех, кто может быть заинтересован в "для циклических вложений" глубже, чем 2 уровня.Как видите, его легко распространить на столько «вложений», сколько вам нравится.Оригинальный кредит идет на реализацию VatooVatoo на Java на форумах DaniWeb.

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

<html>
<head>
<script type="text/javascript">
    function loopRecurse(a, b, c)
    {
        if(c >= 2) {
            b++;
            c=0;
            loopRecurse(a, b, c);
            return;
        }
        if(b >= 2) {
            a++;
            b=0;
            loopRecurse(a, b, c);
            return;
        }
        if(a >= 2) return;
        document.write("<div>" + a + "|" + b + "|" + c + "</div>");
        c++;
        loopRecurse(a, b, c);
    }
    loopRecurse(0, 0, 0);
</script>
</head>
<body>
    <!-- output
        0|0|0
        0|0|1
        0|1|0
        0|1|1
        1|0|0
        1|0|1
        1|1|0
        1|1|1
     -->
</body>
</html>
1 голос
/ 21 февраля 2011

То, что вы пытаетесь сделать, объясняется в учебнике Педро Тейшейры Асинхронные итерационные шаблоны .В примерах используется Node.js, но вы можете использовать те же шаблоны в браузере.По сути, вам нужно преобразовать ваши циклы в последовательные обратные вызовы, ожидающие друг друга, чтобы завершить следующий запрос AJAX из успешного обратного вызова предыдущего и т. Д. Это можно сделать, не блокируя браузер, но не в циклах.Смотрите этот учебник.

0 голосов
/ 21 февраля 2011

См. Документацию XMLHttpRequest (связана с MDC, но это не имеет значения). По сути, вы ищете условие request.readyState==4 - при условии, что ваш ajax() возвращает фактический XMLHttpRequest объект.

...