第二个AJAX调用卸载第一个结果

时间:2014-11-26 19:22:50

标签: php javascript ajax

以下代码在页面的onLoad事件中运行。我首先想用getCompany()填充下拉菜单,然后将服务器中的数据填入文本框并选择所选的选项。

这两个函数都可以正常工作,实际上当我重新加载运行调试器的页面并进入所有内容时,它们都会按预期运行。

当我打开页面或用调试器重新加载时,文本框已填满,但选项从下拉列表中消失,为什么会这样?

<script>
        var result;
        function init(){
            var name = window.name;
            name = name.split(",");
            getCompany();
            setTimeout(200);
            if (name[0] = "update"){
                id = name[1];
                getTenant(id);
                //get the info for the line that called the edit function
                //fill fields with information from server
            }
        }

        function getCompany() { 
            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 x() {
                if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                    document.getElementById("company").innerHTML = xmlhttp.responseText;
                }
            }
            xmlhttp.open("GET","getCompany.php",true);
            xmlhttp.send();
        }

        function getTenant(id){
            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 y() {
                if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                    result = xmlhttp.responseText;
                    result = result.split(",");
                    //fill the form with old information
                    document.getElementById("fname").value = result[0];
                    document.getElementById("lname").value = result[1];
                    document.getElementById("company").selectedIndex = result[2];
                    document.getElementById("phone").value = result[3];
                    document.getElementById("email").value = result[4];
                    document.getElementById("crm").value = result[5];
                }
            }
            xmlhttp.open("GET","getTenant.php?p=" + id,true);
            xmlhttp.send();
        }
    </script>

3 个答案:

答案 0 :(得分:2)

我假设您在第二个请求中填入数据的输入字段属于从第一个请求获取的数据。我还假设您使用setTimeout()来延迟第二个请求...

Javascripts是单线程的。为了提供异步行为,js使用了回调机制。在向服务器发送请求后,js不会等到响应响起。 JS继续执行其余的代码,直到服务器的结果出现。当响应来自服务器时,执行回调函数xmlhttp.onreadystatechange中的代码。因此,这两个请求可能几乎同时发生,因此第二个请求的响应可能会在第一个响应之前发生,这会导致您认为是错误的行为。

调试时,逐行执行。因此,在获得第二个请求的响应之前,有足够的时间来获取第一个请求的响应。

作为解决方案,您可以在第一个请求的代码中的xmlhttp.onreadystatechange回调中移动第二个请求的代码。然后,由于在获取结果后始终执行回调,因此在第一个请求的响应到来之后发送第二个请求。

您可以谷歌了解异步javascript 并详细了解...

<script>
    var result;
    function init(){
        var name = window.name;
        name = name.split(",");
        getCompany(name);
    }

    function getCompany(name) { 
        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 x() {
            if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                document.getElementById("company").innerHTML = xmlhttp.responseText;
                if (name[0] == "update"){
                   id = name[1];
                   getTenant(id);
                   //get the info for the line that called the edit function
                   //fill fields with information from server
                }
            }
        }
        xmlhttp.open("GET","getCompany.php",true);
        xmlhttp.send();
    }

    function getTenant(id){
        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 y() {
            if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                result = xmlhttp.responseText;
                result = result.split(",");
                //fill the form with old information
                document.getElementById("fname").value = result[0];
                document.getElementById("lname").value = result[1];
                document.getElementById("company").selectedIndex = result[2];
                document.getElementById("phone").value = result[3];
                document.getElementById("email").value = result[4];
                document.getElementById("crm").value = result[5];
            }
        }
        xmlhttp.open("GET","getTenant.php?p=" + id,true);
        xmlhttp.send();
    }
</script>

答案 1 :(得分:0)

由于getCompany和getTenant方法进行的两次XHR调用之间存在竞争条件,因此发生了这种情况。即使您在进行第一次XHR调用后200ms进行getTenant调用,也无法保证getComapny XHR调用将首先完成。当发生这种情况时,接下来的代码行

document.getElementById("company").innerHTML = xmlhttp.responseText;

从菜单中删除所有选项,并重置所选索引。为了避免这个问题,请不要生成getTenant(id);从init方法调用。而是从getCompany XHR调用的成功处理程序中创建它。

            xmlhttp.onreadystatechange=function x() {
                if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                    document.getElementById("company").innerHTML = xmlhttp.responseText;
                    **getTenant(id);**
                }
            }

答案 2 :(得分:0)

创建两个不同的对象名称而不是一个(xmlhttp)。喜欢

  • in&#39; getCompany()&#39;功能对象名称是&#39; xmlhttp&#39;
  • in&#39; getTenant()&#39;功能将对象名称更改为&#39; xmlTalenthttp&#39; (或您希望的任何其他名称)