Как остановить выполнение цикла до завершения выполнения метода 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 глобальной переменной, и я немного изменил ваш код.