将属性赋予xmlhttprequest对象

时间:2014-03-31 07:08:31

标签: javascript html

我有以下代码:

<head>
<script>

function startChanging() {
    var elems = document.getElementsByTagName("img");

    for(var i=0; i < elems.length; i++)
    {
        var xmlhttp;
        if (window.XMLHttpRequest)
        {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else
        {
            // code for IE6, IE5
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }

        xmlhttp["elem"] = elems[i];
        xmlhttp.onreadystatechange=function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                this["elem"].src = xmlhttp.responseText;
            }
        }
        xmlhttp.open("GET", "http://myurl.com/somescript.php", true);
        xmlhttp.send();
    }

};

</script>
</head>

<body onload="startChanging()">
<img src="https://www.google.com/images/srpr/logo11w.png">
<br/>
<img src="https://www.google.com/images/srpr/logo11w.png">
<br/>
<img src="https://www.google.com/images/srpr/logo11w.png">
</body>

即使我为每次迭代创建了一个XMLHttpRequest的新实例并将当前元素添加到属性,但当请求返回响应时,只会更改最后一个img元素。

我正在寻找一个简单的解决方案来更改src元素的img,而不会在响应到来时再次遍历所有元素。我想要一个纯粹的Javascript解决方案(阅读:没有JQuery)。

我肯定在这里做错了我只是不明白什么。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

for循环中,您正在覆盖xmlhttp变量,因此当您进入onreadystatechage函数并检查xmlhttp.readyState的值时,它将不会检查正确的对象。

我建议这个修改可以改变两件事:

  1. 它将每个ajax调用放入它自己的IIFE中,使xmlhttp变量与每个ajax调用分开。
  2. 它将elems[i]传递到闭包中,因此您无需执行属性保存黑客攻击。
  3. 代码:

    function startChanging() {
        var elems = document.getElementsByTagName("img");
    
        for(var i=0; i < elems.length; i++)
        {
            (function(obj) {
                var xmlhttp;
                if (window.XMLHttpRequest)
                {
                    // code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp=new XMLHttpRequest();
                }
                else
                {
                    // code for IE6, IE5
                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                }
    
                xmlhttp.onreadystatechange=function()
                {
                    if (xmlhttp.readyState==4 && xmlhttp.status==200)
                    {
                        obj.src = xmlhttp.responseText;
                    }
                }
                xmlhttp.open("GET", "http://myurl.com/somescript.php", true);
                xmlhttp.send();
            })(elems[i]);
        }
    
    };
    

答案 1 :(得分:1)

一种可能的方法:

xmlhttp.onreadystatechange = function() {
  if (this.readyState === 4 && this.status === 200) {
    this.elem.src = this.responseText;
  }
}

如您所见,我已将该处理程序函数中对xmlhttp的所有引用替换为this

问题是即使你已经在循环的每一步创建了一个新的AJAX服务对象,每个新创建的'readystatechange'处理函数都引用xmlhttp下已知的同一个对象变量

通常,当有人使用在同一循环中创建的函数引用的循环内声明的变量时,这是一个非常常见的问题。偶然发现一两次,你会开始看到这种模式。 )

答案 2 :(得分:0)

xmlhttp.send();

将数据放入send方法:

xmlhttp.send(data);

来源:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest

void send();
void send(ArrayBuffer data);
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);

data是一个JavaScript变量,你可以放任何东西。如果你想要多部分消息,你可以使用var data = new FormData();并使用data.append('image', file);将数据放入其中,例如通过ajax上传文件。 如果没有多部分,只需输入任何内容:

data = { images: document.getElementsByTagName("img") }