2010-03-01 14 views
16

sto sviluppando una classe ausiliaria semplice per inviare le richieste utilizzando XmlHttpRequest (codice qui sotto). Ma non posso farlo funzionare. In Google Chrome, per esempio, ho l'errore INVALID_STATE_ERR: DOM Exception 11 e ad altri browser ottengo un == stato 0.INVALID_STATE_ERR: DOM Exception 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); 
} 

Esempio di utilizzo:

<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

Non riesco a immaginare il motivo per cui ci si briga di scrivere qualcosa del genere, tranne forse per il divertimento. Questo non risponde alla tua domanda, ma vi consiglio di fare che "per" loop essere: "for (var e in args) ..." – Pointy

+0

Non è per divertimento. Questo verrà eseguito in un browser incorporato e il codice utilizza molto le richieste HTTP, ecco perché l'ho inserito in una classe per semplificarne l'utilizzo. Inoltre, il codice non è ancora completo! – Andres

+2

Beh, perché non dovresti semplicemente usare uno dei tanti, molti framework open source che già forniscono tale funzionalità? Hanno già risolto i bug e risolto i problemi del browser. – Pointy

risposta

9

Indipendentemente da ciò, è possibile semplificare il metodo di SendRequest creando un mixin invece di utilizzare un gigante switch.

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); 
}; 

Anche essere attenti: i tuoi esistenti for..in loop hanno due problemi distinti:

  1. non si sta utilizzando var e causando un mondiale da creare: for (e in args) dovrebbe essere for (var e in args)
  2. Ogni volta che si utilizza for..in, si dovrebbe sempre controllare per assicurarsi che ogni chiave è un membro diretto di un oggetto, e non qualcosa ereditato inavvertitamente attraverso prototipo

.

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

problema in questa libreria AJAX .

XHR.setRequestHeader() deve essere chiamato dopo 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

Sì, l'ho già provato prima di chiedere qui, basato sul post http://lists.apple.com/archives/dashboard-dev/2006/Dec/msg00007.html e non ha funzionato. – Andres

+0

"Problema in questa libreria ajax XHR.setRequestHeader() deve essere chiamato dopo XHR.open()" -> grazie mille;) – daveoncode

6

Di solito questo errore si verifica con l'XMLHttpRequest quando si chiama il metodo aperto con asincrono = true, o si lascia il parametro asincrona undefined così il default è asincrona, e poi si accede alle proprietà di stato o responseText. Queste proprietà sono disponibili solo dopo aver effettuato una chiamata sincrona o dopo aver predisposto ReadyState (una volta che la chiamata asincrona risponde). Ti suggerisco di provare prima con async = false, quindi passare a true e utilizzare onReadyStateChange.

+0

esattamente quello di cui avevo bisogno: ho controllato lo stato, ma non per readyState. Ma è importante avere readyState == 4 prima di controllare qualcos'altro – Dmitry

+0

Evidenziato qualcosa di critico e non così ovvio. Grazie. – Sebas

3

Nel mio caso l'errore si è verificato quando ho tentato di accedere a xhr.statusText all'interno del metodo xhr.onreadystatechange, tuttavia il recupero di xhr.readyState è andato bene.

Problemi correlati