ожидание успешного завершения ajax перед тем, как перейти к следующей итерации - PullRequest
0 голосов
/ 13 февраля 2012

У меня есть цикл for, который перебирает ассоциативный массив. Для каждой записи я должен сделать ajax-запрос и заполнить другой массив полученными данными.
Проблема в том, что обратный вызов успеха является асинхронным, поэтому он запускается только после повторения цикла. это означает, что мой массив данных заполнен несколькими копиями последнего результата запроса ajax. Это мой код (упрощенно):

var channels = {  
    "misured": "channel_misured",  
    "plan": "channel_plan"  
};
var data;  //Initial data is empty

function getData() {
    data = new Array();

    for (var seriesData in channels) {
        var currentData = new Array();
        $.ajax({
            type: "GET",
            url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?',
            dataType: "json",
            async: false,
            success: function (json) {
                var time = new Date().getTime() + 3600000;
                for (var i = 0; i < json.length; i++) {
                    currentData.push({
                        x: time + i * 30000,
                        y: json[i]
                    });
                }

                data.push({
                    id: seriesData,
                    name: "Production " + seriesData,
                    data: currentData
                });

            }, error: function () {
                console.log("error", this);
            }
        });
    }
}

Таким образом, данные имеют 2 элемента (правильно), но оба они взяты из "plan_channel" (это мой источник данных). Я знаю, что это классическая, хорошо известная «проблема» (или особенность) запросов ajax, но я не понимаю, как мне от нее избавиться.
Не могли бы вы рассказать, как дождаться успешного завершения обратного вызова, прежде чем перейти к следующей итерации?

Ответы [ 2 ]

1 голос
/ 13 февраля 2012

Для синхронных вызовов AJAX вы не можете использовать обработчик успеха и должны возвращать результаты после завершения вызова.

Попытка использования Amplify.js (http://amplifyjs.com/) с asyc, установленным в false; это довольно легко использовать и аккуратнее, чем функция jjuery ajax. Не откладывайте на добавление дополнительной библиотекой.

Обновление # 1

Вы просто должны сделать это

function getData() {
    data = new Array();

    for (var seriesData in channels) {
        var currentData = new Array();


    amplify.request.define( "ajaxExample1", "ajax", {
        url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?',
        dataType: "json",
        async: false,
        type: "GET"
    });

    // later in code
    amplify.request( "ajaxExample1", function( json ) {
        var time = new Date().getTime() + 3600000;
        for (var i = 0; i < json.length; i++) {
            currentData.push({
                x: time + i * 30000,
                y: json[i]
            });
        }

        data.push({
            id: seriesData,
            name: "Production " + seriesData,
            data: currentData
        });
    });

    }
}
1 голос
/ 13 февраля 2012

Это единственный способ (изо всех сил), который я вижу, чтобы реорганизовать ваш код.Это немного бессмысленно, хотя.Вы настроили все неправильно IMO, вы не должны делать это таким образом.Лучший способ сделать это - отправить весь массив одним ajax-запросом в ajax-скрипт, разобраться со всем этим в php (или где-то еще) и выложить его обратно в том формате, который вы хотите в javascript.,В противном случае вам лучше найти лучший способ сделать это.Например, вместо цикла for вы можете получить ajax-запрос, который вызывает вызов функции getData() при успешном вызове.

// add a global var...
var inLoop;
function getData() {
    data = new Array();

    for (var seriesData in channels) {
        inLoop = true; // set to true
        var currentData = new Array();

        $.ajax({
            type: "GET",
            url: 'http://' + serverAddress + ':' + serverPort + '/GetChannelBufferAsJsonp?channelName=' + channels[seriesData] + '&callback=?',
            dataType: "json",
            async: false,
            success: function (json) {
                // set inLoop to false to get out of loop below
                inLoop = false;
                var time = new Date().getTime() + 3600000;
                for (var i = 0; i < json.length; i++) {
                    currentData.push({
                        x: time + i * 30000,
                        y: json[i]
                    });
                }

                data.push({
                    id: seriesData,
                    name: "Production " + seriesData,
                    data: currentData
                });

            }, error: function () {
                console.log("error", this);
            }
        });

        // loop round this bit for a while
        while(inLoop){
          // wait
        }
    }


}

Вот как я бы переписал приведенный выше код:

var channels = {
  "first" : "hello world",
  "second" : "goodbye world"
}

function getData(channel){
  $.ajax({
    url: 'http://whatever.com/channel='+channel,
    success: function(){
      getData(nextchannel);
    }
  });
}

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

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