2010-03-01 48 views
16

我正在開發一個簡單的輔助類來使用XmlHttpRequest發送請求(代碼如下)。但我不能讓它工作。在谷歌瀏覽器,例如,我得到的錯誤INVALID_STATE_ERR: DOM Exception 11,並在其他瀏覽器,我收到了狀態==使用的0INVALID_STATE_ERR:DOM異常11

//@method XRequest: Object constructor. As this implements a singleton, the object can't be created calling the constructor, GetInstance should be called instead 
function XRequest() { 
    this.XHR = XRequest.CreateXHR(); 
} 
XRequest.instance = null; 

//@method static GetInstance: Creates a singleton object of type XRequest. Should be called whenever an object of that type is required. 
//@return: an instance of a XRequest object 
XRequest.GetInstance = function() { 
    if(XRequest.instance == null) { 
     XRequest.instance = new XRequest(); 
    } 
    return XRequest.instance; 
} 

//@method static CreateXHR: Implments a basic factory method for creating a XMLHttpRequest object 
//@return: XMLHttp object or null 
XRequest.CreateXHR = function() { 
    var xhr = null; 
    var factory = [ 
     function() { return new XMLHttpRequest(); }, 
     function() { return new ActiveXObject("Msxml2.XMLHTTP"); }, 
     function() { return new ActiveXObject("Microsoft.XMLHTTP"); } 
    ]; 

    for(var i = 0; i < factory.length; ++i) { 
     var f = factory[i]; 
     xhr = f(); 
     if(xhr) return xhr; 
    } 
    return null; 
} 

XRequest.prototype.SetRequestHeader = function(name, value) { 
    if(this.XHR) { 
     this.XHR.setRequestHeader(name, value); 
    } 
} 

XRequest.prototype.SendRequest = function(args) { 
    var async = true; 
    var type = ""; 
    var url = ""; 
    var username = ""; 
    var password = ""; 
    var body = null; 
    var success = null; 
    var failure = null; 

    for(e in args) { 
     switch(e) { 
      case "async": 
       async = args[e]; 
       break; 
      case "type": 
       type = args[e]; 
       break; 
      case "success": 
       success = args[e]; 
       break; 
      case "failure": 
       failure = args[e]; 
       break; 
      case "url": 
       url = args[e]; 
       break; 
      case "username": 
       username = args[e]; 
       break; 
      case "password": 
       password = args[e]; 
       break; 
      case "body": 
       body = args[e]; 
      break; 
      case "setHeader": 
       var h = args[e].split(":"); 
       if(h.length == 2) { 
        this.SetRequestHeader(h[0], h[1]); 
       } 
       break; 
     } 
    } 

    var that = this; 
    this.XHR.onreadystatechange = function() { 
     alert("readyState == " + that.XHR.readyState + " status == " + that.XHR.status); 
     if(that.XHR.readyState == 4) { 
      if(that.XHR.status == 200 || that.XHR.status == 0) { 
       if(success) success(that.XHR); 
      } else { 
       if(failure) failure(); 
      } 
     } 
    }; 
    this.XHR.open(type, url, async, username, password); 
    this.XHR.send(body); 
} 

例子:

<script language="javascript"> 
    function onLoad() { 
     var x = XRequest.GetInstance(); 
     x.SendRequest({type:"GET", 
      setHeader:"Accept:text/html, image/png, image/*, */*", 
      url: "http://your_server.com/getData?param1=test", 
      success:onSuccess, failure:onFail 
     }); 
    } 

    function onSuccess(obj) { 
     alert("OK");     
    } 

    function onFail() { 
     alert("Not at this time!"); 
    } 
</script> 
+0

我無法想象爲什麼你會寫這樣的東西,除了可能是爲了好玩。這並不回答你的問題,但我建議你讓「for」循環爲:「for(var e in args)...」 – Pointy 2010-03-01 16:56:04

+0

這不是爲了好玩。這將在嵌入式瀏覽器中運行,代碼使用http請求很多,這就是爲什麼我將它放在類中以簡化其使用。此外,代碼還不完整! – Andres 2010-03-01 17:08:33

+2

那你爲什麼不使用已經提供這種功能的衆多開源框架之一呢?他們已經解決了錯誤,解決了跨瀏覽器問題。 – Pointy 2010-03-01 17:16:05

回答

9

無論如何,你可以通過創建一個混合,而不是使用一個巨型switch簡化SendRequest方法。

XRequest.prototype.SendRequest = function(params) { 
    var defaultParams = { 
     async: true, 
     type:  "", 
     url:  "", 
     username: "", 
     password: "", 
     body:  null, 
     success: null, 
     failure: null 
    }; 

    for (var i in defaultParams) { 
     if (defaultParams.hasOwnProperty(i) && typeof params[i] == "undefined") { 
      params[i] = defaultParams[i]; 
     } 
    } 

    var that = this; 
    this.XHR.onreadystatechange = function() { 
     if (that.XHR.readyState == 4) { 
      if (that.XHR.status == 200 || that.XHR.status == 0) { 
       if (params.success) { 
        params.success(that.XHR); 
       } 
      } else { 
       if (params.failure) { 
        params.failure(); 
       } 
      } 
     } 
    }; 

    this.XHR.open(
     params.type, parms.url, params.async, params.username, params.password 
    ); 

    // It doesn't make sense to have a for/switch here when you're only handling 
    // one case 
    if (params.setHeader) { 
     var h = params.setHeader.split(":"); 
     if (h.length == 2) { 
      this.SetRequestHeader(h[0], h[1]); 
     } 
    } 

    this.XHR.send(params.body); 
}; 

另外要注意:您現有for..in迴路有兩種截然不同的問題:

  1. 您沒有使用var並造成全球被創建:for (e in args)應該for (var e in args)
  2. 當你使用for..in,你應該經常檢查以確保每個鍵是對象的直接成員,而不是通過原型無意中繼承的東西

for (var i in obj) { 
    if (obj.hasOwnProperty(i)) { 
     // do stuff here 
    } 
} 
40

問題在這個Ajax庫。

XHR.setRequestHeader()必須在XHR.open()之後調用。

// @method XRequest: Object constructor. As this implements a singleton, the object can't be created calling the constructor, GetInstance should be called instead 
function XRequest() 
{ 
    this.XHR = XRequest.CreateXHR(); 
} 

XRequest.instance = null; 


// @method static GetInstance: Creates a singleton object of type XRequest. Should be called whenever an object of that type is required. 
// @return: an instance of a XRequest object 
XRequest.GetInstance = function() 
{ 
    if(XRequest.instance == null) 
    { 
     XRequest.instance = new XRequest(); 
    } 

    return XRequest.instance; 
} 

// @method static CreateXHR: Implments a basic factory method for creating a XMLHttpRequest object 
// @return: XMLHttp object or null 
XRequest.CreateXHR = function() 
{ 
    var xhr = null; 
    var factory = [ 
        function() { return new XMLHttpRequest(); }, 
        function() { return new ActiveXObject("Msxml2.XMLHTTP"); }, 
        function() { return new ActiveXObject("Microsoft.XMLHTTP"); } 
       ]; 

    for(var i = 0; i < factory.length; ++i) 
    { 
     var f = factory[i]; 
     xhr = f(); 
     if(xhr) 
      return xhr; 
    } 

    return null; 
} 

XRequest.prototype.SetRequestHeader = function(name, value) 
{ 
    if(this.XHR) 
    { 
     //alert(name+'|||'+value); 
     this.XHR.setRequestHeader(name, value); 
    } 
} 

XRequest.prototype.SendRequest = function(args) 
{ 
    var async = true; 
    var type = ""; 
    var url = ""; 
    var username = ""; 
    var password = ""; 
    var body = null; 
    var success = null; 
    var failure = null; 

    for(e in args) 
    { 
     switch(e) 
     { 
      case "async": 
       async = args[e]; 
       break; 

      case "type": 
       type = args[e]; 
       break; 

      case "success": 
       success = args[e]; 
       break; 
      case "failure": 
       failure = args[e]; 
       break; 

      case "url": 
       url = args[e]; 
       break; 

      case "username": 
       username = args[e]; 
       break; 

      case "password": 
       password = args[e]; 
       break; 

      case "body": 
       body = args[e]; 
       break; 
     } 
    } 

    var that = this; 
    this.XHR.onreadystatechange = function() 
     { 
      alert("readyState == " + that.XHR.readyState + " status == " + that.XHR.status); 
      if(that.XHR.readyState == 4) 
      { 
       if(that.XHR.status == 200 || that.XHR.status == 0) 
       { 
        if(success) 
         success(that.XHR); 
       } 
       else 
       { 
        if(failure) 
         failure(); 
       } 
      } 
     }; 

    this.XHR.open(type, url, async, username, password); 
    for(e in args) 
    { 
     switch(e) 
     { 
      case "setHeader": 
       var h = args[e].split(":");    
       if(h.length == 2) 
       { 
        this.SetRequestHeader(h[0], h[1]); 
       } 
       break; 
     } 
    } 
    this.XHR.send(body); 
} 
+0

是的,我已經在此之前嘗試過,基於該帖子http://lists.apple.com/archives/dashboard-dev/2006/Dec/msg00007.html,並沒有工作。 – Andres 2010-03-01 18:54:43

+0

「這個ajax庫中的問題,XHR.setRequestHeader()必須在XHR.open()」 - >「之後調用很多;) – daveoncode 2012-10-06 12:18:26

6

通常與XMLHttpRequest的,當你調用open方法與異步=真,就會出現這個錯誤,或者你離開未定義所以它默認爲異步異步參數,然後你進入狀態或responseText的屬性。這些屬性僅在進行同步調用之後或ReadyState準備就緒(一旦異步調用響應)後纔可用。我建議你先用async = false嘗試,然後切換到true並使用onReadyStateChange。

+0

正是我所需要的:我檢查了狀態,但不是readyState。但是在檢查其他東西之前準備好狀態== 4很重要 – Dmitry 2012-12-01 11:23:10

+0

指出一些重要的事情並不那麼明顯。謝謝。 – Sebas 2013-07-16 00:21:34

3

在我的情況下,當我試圖在xhr.onreadystatechange方法中訪問xhr.statusText時發生了錯誤,但是檢索xhr.readyState進行得很好。

相關問題