【问题标题】:Javascript Functions Confusing AJAX Responses from CGI Request/Response混淆来自 CGI 请求/响应的 AJAX 响应的 Javascript 函数
【发布时间】:2012-10-22 17:08:47
【问题描述】:

我有 3 个从 HTML 页面中的正文 onload 调用的 Javascript 函数。

每个 Javascript 函数都包含在它自己的 Javascript 文件中。每个 Javascript 文件对应于服务器上的另一个 CGI 脚本。

bodyonload.js 看起来像:

function bodyOnload() {
 getElementsA();
 getElementsB();
 getElementsC();
}

每个 getElements 函数只调用一个 CGI 脚本来获取 3 个不同选择框的内容。

问题在于所有 3 个函数都是异步调用的,因此选择框会得到错误的结果。这几乎就像 3 个函数相互踩踏,并将 CGI 响应放在错误的选择框中。我知道 CGI 的响应是正确的。如果我从其他函数中连续调用每个函数,这很好。就像从第一个函数调用第二个函数,从第二个函数调用第三个函数一样。它们同时运行的异步特性似乎导致了问题。

这是包含 getElements 函数的每个 javascript 文件的通用代码。

function getElementsA() {
    strURL = "http://test.com/scriptA.cgi";
    var xmlHttpReq = false;
    var self = this;

    // Mozilla/Safari
    if (window.XMLHttpRequest) {
        self.xmlHttpReq = new XMLHttpRequest();
    }
    // IE
    else if (window.ActiveXObject) {
        self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    self.xmlHttpReq.open('POST', strURL, true);
    self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    self.xmlHttpReq.onreadystatechange = function() {
        if (self.xmlHttpReq.readyState == 4) {
            fillselectboxA(self.xmlHttpReq.responseText);
        }
    }

 self.xmlHttpReq.send();

}

function fillselectboxA(str)
 {
  document.getElementById("selectBoxA").length=0;
  var results = new Array();
  results = str.split(/\n/);
  var size = results.length;
  var select = document.getElementById("selectBoxA");
  for (x=0;x<size;x++)
   {
    var element = results[x];
    select.options.add(new Option(element, x))
   }
 } 

-------------------

function getElementsB() {
    strURL = "http://test.com/scriptB.cgi";
    var xmlHttpReq = false;
    var self = this;

    // Mozilla/Safari
    if (window.XMLHttpRequest) {
        self.xmlHttpReq = new XMLHttpRequest();
    }
    // IE
    else if (window.ActiveXObject) {
        self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    self.xmlHttpReq.open('POST', strURL, true);
    self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-  urlencoded');
    self.xmlHttpReq.onreadystatechange = function() {
        if (self.xmlHttpReq.readyState == 4) {
            fillselectboxB(self.xmlHttpReq.responseText);
        }
    }

 self.xmlHttpReq.send();

}

function fillselectboxB(str)
 {
  document.getElementById("selectBoxB").length=0;
  var results = new Array();
  results = str.split(/\n/);
  var size = results.length;
  var select = document.getElementById("selectBoxB");
  for (x=0;x<size;x++)
   {
    var element = results[x];
    select.options.add(new Option(element, x))
   }
 } 

------------------------

function getElementsC() {
    strURL = "http://test.com/scriptC.cgi";
    var xmlHttpReq = false;
    var self = this;

    // Mozilla/Safari
    if (window.XMLHttpRequest) {
        self.xmlHttpReq = new XMLHttpRequest();
    }
    // IE
    else if (window.ActiveXObject) {
        self.xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    self.xmlHttpReq.open('POST', strURL, true);
    self.xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    self.xmlHttpReq.onreadystatechange = function() {
        if (self.xmlHttpReq.readyState == 4) {
            fillselectboxC(self.xmlHttpReq.responseText);
        }
    }

 self.xmlHttpReq.send();

}

function fillselectboxC(str)
 {
  document.getElementById("selectBoxC").length=0;
  var results = new Array();
  results = str.split(/\n/);
  var size = results.length;
  var select = document.getElementById("selectBoxC");
  for (x=0;x<size;x++)
   {
    var element = results[x];
    select.options.add(new Option(element, x))
   }
 } 

【问题讨论】:

  • 除非你有理由(你可能),否则你可能希望onreadystatechange 方法中的if 语句为if (self.xmlHttpReq.readyState == 4 &amp;&amp; self.xmlHttpReq.status == 200) {
  • getElementsB 是否调用了fillselectbox 以外的其他名称?我想你介意发布getElementsB 及其相关的 Javascript 吗?
  • 设置元素的长度也没有意义document.getElementById("divA").length=0;

标签: javascript ajax asynchronous cgi response


【解决方案1】:

这三个函数几乎是互相踩踏的

正是发生了什么,当您调用getElementsB 时,您将覆盖getElementsA 上设置的onreadystatechange 处理程序,然后在您调用getElementsC 时再次覆盖。这是因为thisself 是所有三个函数中的全局对象(假设它们都类似于getElementsA)。

您可以通过将函数调用更改为对象实例化来规避这种情况:

function bodyOnload() {
  new getElementsA();
  new getElementsB();
  new getElementsC();
}

【讨论】:

  • 是的,就是这样。非常感谢。作为对象的函数对我来说有点新。这使一堆事情变得更加清晰。谢谢!!!!
  • @user770395 关键是this 的行为,根据上下文可以有不同的值。有关详细信息,请参阅此问题:stackoverflow.com/questions/3320677/this-operator-in-javascript
猜你喜欢
  • 2012-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 2010-10-23
  • 1970-01-01
相关资源
最近更新 更多