делать параллельные запросы AJAX - PullRequest
0 голосов
/ 21 июля 2011

У меня есть код javascript, который выполняет эти вещи в цикле

  1. создает элемент div, добавляет его к dom и получает его ссылку
  2. передает эту ссылкук функции, которая делает запрос ajax post
  3. , задает ответ запроса ajax на innerHTML переданной ссылки на элемент

здесь код

window.onload = function () {
    var categories = document.getElementById('categories').children;
    for (i = 0; i < categories.length; i++) {
        var link = categories[i].children[1].children[0].attributes['href'].nodeValue;
        var div = document.createElement('div');
        div.className = "books";
        div.style.display = "none";
        categories[i].appendChild(div);
        getLinks(link, div);
    }
}

function getLinks(url, div) {
    xhr = new XMLHttpRequest();
    xhr.open('POST', 'ebook_catg.php', true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    url = encodeURIComponent(url)
    var post = "url=" + url;
    xhr.node=div;                         //in response to Marc B's suggestion
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            xhr.node.innerHTML = xhr.responseText;
            xhr.node.style.display = "block";
        }
    }
    xhr.send(post);
}

теперь, когда я проверяю это в firebug, я вижу, что элемент div создан и добавлен к элементу categories, а его отображение установлено на hidden.также ajax post запросы отправляются и ответ принимается, как и ожидалось.Но свойство innerHTML div не установлено, и его отображение не установлено на block.Это означает, что функция getLinks теряет ссылку div.

когда я набираю console.log(div) в консоли Firefox, он говорит ReferenceError: div is not defined.

Может кто-нибудь объяснить, что здесь происходит?


в ответ на комментарий Фрэнкса я изменил readystate на readyState, и я могу прикрепить ответ последнего запроса AJAX к DOM.так что становится очевидным, что ссылка div теряется.

Ответы [ 4 ]

2 голосов
/ 21 июля 2011

Помните, что внутренности обработчиков ответов не «зациклены», когда определен обратный вызов, поэтому «текущее» значение div var не внедряется в определение функции.Это будет разрешено только тогда, когда функция действительно выполнится, к этому времени она могла бы быть установлена ​​на какой-то совершенно другой div или была сброшена на нуль, поскольку область родительской функции была уничтожена.

Вы можете сохранитьЗначение div в качестве атрибута данных объекта xhr, который затем можно получить из обратного вызова:

xhr.data('thediv', div);
xhr.onreadystatechange = function () {
        if (xhr.readystate == 4) {
            div = xhr.data('thediv');
     etc....
2 голосов
/ 21 июля 2011

Это потому, что вы используете публичную (глобальную) переменную div, которая постоянно перезаписывается.

Попробуйте это в вашем for loop:

for (i = 0; i < categories.length; i++) {
    var link = categories[i].children[1].children[0].attributes['href'].nodeValue;
    var div = document.createElement('div'); //USE var!
    div.className = "books";
    div.style.display = "none";
    categories[i].appendChild(div);
    getLinks(link, div);
}
1 голос
/ 22 июля 2011

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

// changed the name to `d` because div seems to already be a global var.
function getLinks(url, d) {
    // make xhr a local variable so it won't get re-written.
    var request = new XMLHttpRequest();
    request.open('POST', 'ebook_catg.php', true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    url = encodeURIComponent(url)
    var post = "url=" + url;
    request.onreadystatechange = function () {
        // when the request was global, this would be false until the last 
        // request completed
        if (request.readyState == 4) {
            // since d only exists as a parameter to getLinks, this should 
            // already be bound when the onreadystatechange is created.
            d.innerHTML = request.responseText;
            d.style.display = "block";
        }
    }
    request.send(post);
}

Итак, почему я просто делал такие странные, странные вещи? Что ж, похоже, что div был назначен как глобальная переменная, и хотя JS должен всегда искать имя параметра функции для привязки, мы хотим устранить все возможные проблемы. Поэтому я изменил имя этой переменной. Затем я установил xhr для отображения локальной переменной с ключевым словом var. Я также изменил имя на запрос. Еще раз, это не должно иметь значения - переменная означает, что переменная будет привязана к этой области, но изменение безвредно, и, поскольку я не знаю, что еще у вас есть, я решил устранить двусмысленности. Если это не поможет JS, это поможет читателю.

Примечание:

Важной частью вышеприведенного ответа является var перед запросом.

0 голосов
/ 22 июля 2011

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

var xhr=new Array();

window.onload=function() {
var categories=document.getElementById('categories').children;
for(i=0;i<categories.length;i++)
{
var link=categories[i].children[1].children[0].attributes['href'].nodeValue;
var div=document.createElement('div');
div.className="books";
div.style.display="none";
categories[i].appendChild(div);
getLinks(link,div,i);
}
}

function getLinks(url,div,i)
{
xhr[i]=new XMLHttpRequest();
xhr[i].open('POST','ebook_catg.php',true);
xhr[i].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
url=encodeURIComponent(url)
var post="url="+url;
xhr[i].node=div;
xhr[i].onreadystatechange=function() {
if(xhr[i].readyState==4)
{
xhr[i].node.innerHTML=xhr[i].responseText;
xhr[i].node.style.display="block";
}
}
xhr[i].send(post);
} 

Я не отмечаю его какпринято, потому что я до сих пор не понимаю, почему мне нужно использовать массив xhr, так как локального объекта xhr должно быть достаточно, потому что каждый раз, когда выполняется функция onreadystate, он имеет ссылку на объект xhr.Теперь, поскольку функции javascript также являются объектами, каждый экземпляр функции onreadystate должен иметь свою собственную ссылку на объект xhr, и поэтому мне не нужно создавать массив xhr s . Пожалуйста, поправьте меня, если я здесь не прав

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