2016-09-01 2 views
0

Я хотел бы запросить цикл 100 раз по запросу ajax с циклом for. Это мой код:Ajax request in for loop

for(var i=1; i<100; i++) 
{ 
    var num = i+1; 

    var request = new XMLHttpRequest(); 
    request.open("GET", "http://localhost/test/1/2/main.php?t="+num+"", true); 
    request.send(null); 
    request.onreadystatechange = function() { 

    if (request.readyState == 4) { 

     var parser = new DOMParser(); 
     var doc = parser.parseFromString(request.responseText, "text/html"); 

     var rows = doc.getElementsByTagName("table")[0].getElementsByTagName("tbody")[0].getElementsByTagName("tr"); 

     var sum = 0; 
     for(var j=0; j<rows.length;j++) 
     { 
      sum += parseInt(rows[j].getElementsByTagName("td")[7].textContent.trim()); 
     } 
     alert(num); 
    } 


    }   

}

Но это не работает. В консоли я вижу 100 раз эту информацию:

XHR finished loading: GET " http://localhost/test/1/2/main.php?t=2 ". XHR finished loading: GET " http://localhost/test/1/2/main.php?t=3 ".

т.д. Так что все должно быть в порядке. Но я вижу предупреждение только 14 раз (я не сейчас почему 14), нет 100.

Почему эта программа не работает?

+0

Не могли бы вы попробуйте использовать для цикл внутри функции onreadystatechange, потому что вы на самом деле вызываете его столько раз. Вы хотите сделать это, или только ваш код внутри этой функции, который нужно загружать 100 раз? – Owner

+0

При удалении 'если (request.readyState == 4)' я получаю предупреждение 11times и консоль показывает эту ошибку (?): 'неперехваченным TypeError: Не удается прочитать свойство 'getElementsByTagName' из undefined' в строке' вар rows = doc.getElementsByTagName ("table") [0] .getElementsByTagName ("tbody") [0] .getElementsByTagName ("tr"); ' – Star089

+0

Просто рекомендация: вызовы Ajax можно упростить, а совместимость с crossbrowser гарантирована, когда используя [jQuery] (http://jquery.com) и его ['jQuery.ajax()') (http://api.jquery.com/jQuery.ajax/). – SaschaM78

ответ

0

Пожалуйста, под кодом. Это позволит отключить вызов ajax только после того, как предыдущий будет завершен. Таким образом, никакой аякс-вызов не будет пропущен.

<script type="text/javascript">  
    var num = 0; 
    doAjax(0); 
    function doAjax(arrCount) 
    { 
     if(num<100){ 
      num += 1; 
      var request = new XMLHttpRequest(); 
      request.open("GET", "http://localhost/test/1/2/main.php?t="+num+"", true); 
      request.send(null); 
      request.onreadystatechange = function() { 
       if (request.readyState == 4) { 
        var parser = new DOMParser(); 
        var doc = parser.parseFromString(request.responseText, "text/html"); 
        var rows = doc.getElementsByTagName("table")[0].getElementsByTagName("tbody")[0].getElementsByTagName("tr"); 
        var sum = 0; 
        for(var j=0; j<rows.length;j++) 
        { 
         sum += parseInt(rows[j].getElementsByTagName("td")[7].textContent.trim()); 
        } 
        alert(num); 
        doAjax(num) 
       } 
      } 
     }  
    } 
</script> 
+0

Удивительно! Спасибо ! – Star089

+0

это будет медленнее, чем разрешение нескольких запросов XHR сразу, конечно –

+0

Да, вы правы, но. В этом случае он не пропустит ни одного запроса Ajax. –

0

альтернативный метод с использованием IIFE для закрытия, а некоторые более продвинутые DOM и массив методы, чтобы сделать вещи немного аккуратнее (на мой взгляд)

for(var i=1; i<100; i++) { 
    (function(num) { // [1] 
     var request = new XMLHttpRequest(); 
     request.open("GET", "http://localhost/test/1/2/main.php?t="+num+"", true); 
     request.addEventListener('load', function() { 
      var parser = new DOMParser(); 
      var doc = parser.parseFromString(request.responseText, "text/html"); 
      var sum = [].map.call(// [2] 
       doc.querySelector("table").querySelectorAll("tbody>tr>td:nth-child(8)"), //[3] 
       function(cell) { // [4] 
        return parseFloat(cell.textContent.trim()); 
       }).reduce(function(a, b) { // [5] 
        return a + b; 
       }); 
      alert(num); 
     }); 
     request.send(null); 
    }(i + 1)); 
} 

объяснение:

[1]

function(num) { 
... 
}(i + 1)); 

Это IIFE, который создает замыкание для значения i + 1 (как num)

[2]

[].map.call(x, fn) 

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

в коде х является

[3]

doc.querySelector("table").querySelectorAll("tbody>tr>td:nth-child(8)") 

это получает первую таблицу, а затем 8-й TD от каждого тр в каждом TBODY

если возвращенный HTML только один таблицы, вы можете изменить выше

doc.querySelectorAll("table>tbody>tr>td:nth-child(8)") 

[4] Теперь, Fn в карте обратного вызова

function(cell) { 
    return parseFloat(cell.textContent.trim()); 
} 

Это получает каждую ячейку, и возвращает содержимое разобранного к поплавку

[5] теперь у нас есть массив поплавков - самый простой способ получить сумму массива чисел с массивом #reduce

.reduce(function(a, b) { 
    return a + b; 
}); 

так, теперь сумма, в одном комплексном заявлении получил сумму ячеек

я использую request.addEventListener('load', fn) ...так же, как request.onload = fn - это личный бзик мой возиться со старыми пользователями Internet Explorer: р

load увольняют после того, как данные загрузилась ... так больше не readyState гимнастика нужен