制作并行的ajax请求

时间:2011-07-20 21:36:43

标签: javascript ajax dom

我有javascript代码,可以循环执行这些操作

  1. 创建div元素,将其附加到dom并获取其参考
  2. 将此引用传递给发出ajax post请求的函数
  3. 将ajax请求的响应设置为传递的元素引用的innerHTML
  4. 这是代码

    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的{​​{1}}属性未设置,其显示也未设置为div。 这意味着函数block会丢失getLinks引用。

    当我在firefox控制台中输入div时,它显示为console.log(div)

    有人可以解释这里发生的事情吗?


    为了回应Franks的评论,我将ReferenceError: div is not defined更改为readystate,并且我能够将最后一个ajax请求的响应附加到dom。所以很明显readyState引用正在丢失。

4 个答案:

答案 0 :(得分:2)

这是因为你正在使用一个不断被覆盖的公共(全局)变量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 :(得分:2)

请记住,在定义回调时,响应处理程序内部不会“固定”,因此div var的“当前”值不会嵌入到函数的定义中。它只能在函数实际执行时解析,到那时它可能已被设置为某个完全其他的div,或者由于父函数的范围已被破坏而被重置为null。

您可以将div值存储为xhr对象的数据属性,然后可以在回调中检索该对象:

xhr.data('thediv', div);
xhr.onreadystatechange = function () {
        if (xhr.readystate == 4) {
            div = xhr.data('thediv');
     etc....

答案 2 :(得分:1)

好的,你有一些你不想要的全局变量。经验法则:除非您需要访问函数外部的变量,否则请在其前面放置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关键字反映局部变量。我也更改了要求的名称。再一次,它应该无关紧要 - var意味着变量将绑定到该范围,但更改是无害的,因为我不知道你还有什么,我决定消除歧义。如果它对JS没有帮助,它至少会帮助读者。

注意:

上述答案的重要部分是在请求前面的var。

答案 3 :(得分:0)

这里我回答了我的问题。以下代码有效,我的意思是每篇文章的回复都附加到相应的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对象应该足够了,因为每次{{1函数执行它具有onreadystate对象的引用。现在,由于javascript函数也是对象,因此xhr函数的每个实例都应该有自己的onreadystate对象引用,因此我不需要创建xhr s 的数组。 如果我错了,请纠正我