Как остановить выполнение цикла до завершения выполнения метода DWR, который находится внутри цикла for

Пожалуйста, смотрите этот код:

for(var k=0;k<pods.length;k++){
        var currentQueryList = new Array();
        currentQueryList[0]=pods[k].queryname;
        console.log("Hello :"+i);
        queryBuilderDWRService.getDataForAllPods(currentQueryList, {callback:function(map){
            podsDataMap = map;
            console.log("Hello"+k+":");
            var pod = pods[k];
            displayPod(k, pod, false);
        }});
    }

В этом коде цикл for завершается до вызова queryBuilderDWRService.getDataForAllPods() возвращает фактические данные, которые я использую для получения данных из базы данных.

Это я пытаюсь console.log("Hello"+i); это печать Hello :1, Hello :2, Hello :3, Helllo :4, до длины массива без данных из БД, что означает, что цикл for завершает свое выполнение до queryBuilderDWRService.getDataForAllPods() возвращается.

Что мне нужно, так это то, что когда элемент управления входит в цикл for, он должен завершить выполнение queryBuilderDWRService.getDataForAllPods(), и только после этого может последовать следующая итерация.

Заранее спасибо.

3 ответа

Решение

Вы можете использовать "асинхронную псевдорекурсию" вместо for цикл, с общим шаблоном, который я использую:

var pods = [ ... ];

(function loop() {
    if (pods.length) {
        var pod = pods.shift();   // take (and remove) first element

        // do something with "pod"
        ...

        // recurse - put this inside a finish callback if "do something" is async
        loop();
     }
})();   // closing braces start invocation immediately

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


Примечание: этот шаблон также можно использовать, чтобы избежать ошибки "браузер не отвечает", наблюдаемой при более длительных не асинхронных операциях, заменяя вызов loop() с setTimeout(loop, 0),

Это использование setTimeout превращает синхронную рекурсивную функцию в асинхронную псевдорекурсивную, избегая при этом ошибок переполнения стека.

Единственным недостатком является минимальная задержка в 4 мс между итерациями.

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

Вы должны использовать самовыполняющуюся функцию, называемую замыканием.

var currentQueryList = [];
for(var i=0,l=pods.length; i<l; i++){
  (function(i){
    currentQueryList[0]=pods[i].queryname;
    console.log('Hello :'+i);
    queryBuilderDWRService.getDataForAllPods(currentQueryList, {callback:function(map){
      podsDataMap = map;
      console.log('Hello'+i+':');
      var pod = pods[i];
      displayPod(i, pod, false);
    }});
  })(i);
}

Проблема в том, что когда вы вызываете событие, цикл уже прошел. поскольку i находится в пределах вашего цикла, когда событие запускается, оно ищет значение i, который pods.length-1, так как вы использовали <, Вам нужно, чтобы область вашего приращения была сохранена в отдельных областях памяти, к которым будет обращаться при возникновении события.

Обратите внимание, что вы сделали podsDataMap глобальной переменной, и я немного изменил ваш код.

Другие вопросы по тегам