2012-10-06 17 views
5

El W3C spec sugieren siguiente implementación: Algunos código simple de hacer algo con los datos de un documento XML descabellada través de la red:¿Puede XHR disparar en estado regular varias veces con readyState = DONE?

function processData(data) { 
    // taking care of data 
} 

function handler() { 
    if(this.readyState == this.DONE) { 
    if(this.status == 200 && 
     this.responseXML != null && 
     this.responseXML.getElementById('test').textContent) { 
     // success! 
     processData(this.responseXML.getElementById('test').textContent); 
     return; 
    } 
    // something went wrong 
    processData(null); 
    } 
} 

var client = new XMLHttpRequest(); 
client.onreadystatechange = handler; 
client.open("GET", "unicorn.xml"); 
client.send(); 

¿Es esta aplicación realmente correcto?

Durante la depuración encontré casos cuando el controlador de eventos readystatechanged se llama más de una vez seguidas con el mismo valor de readyState == 4. Supongo que este comportamiento es correcto, ya que las especificaciones indican que cada cambio de estado debe desencadenar evento, y que readyState siempre debe ser igual al estado actual, por lo que si se acumulan varios eventos en la cola de eventos, es bastante obvio que obtendrá múltiples llamadas con readyState == 4.

http://jsfiddle.net/44b3P/ - este es el ejemplo anterior aumentado con llamada de depuración para detener la ejecución justo después de que se envíe la solicitud, y con la alerta() en el processData. Una vez que haya reanudado la ejecución, recibirá 3 alertas.

Este ejemplo de w3c parece ser copia & pegado en varios lugares de la web, en particular, OpenSocial parece manejar eventos xhr de esta manera. ¿Es correcto?

Respuesta

11

También vi el mismo comportamiento (HIZO 200 siendo golpeado más de una vez, es decir, 2 ... n veces) al depurar en Herramientas de desarrollo de Chrome.

para que funcione siempre en modo de depuración, así, me encontré con dos opciones:

  1. Use onload para verificar el éxito de una XMLHTMLRequest W3C Spec

    client.onload = manipulador;

    Esta versión no funcionará en IE8. Debe ser un navegador que implementa la interfaz XMLHttpRequestEventTarget

  2. Quitar el controlador de onreadystatechange tan pronto como usted tiene un estado DONE 200.

    client.onreadystatechange = function() { 
        // check if request is complete 
        if (this.readyState == this.DONE) { 
         if (this.onreadystatechange) { 
          client.onreadystatechange = null; 
          handler(); 
         } 
        } 
    }; 
    

también han abierto un problema en Chromium para este problema, proporcionando a su Fiddle (Gracias!)

+1

Al igual que una adición: utilizando el código proporcionado originalmente, 'this.onreadystatechange = null;' es suficiente, no necesita la referencia original a XHR ('client'). – Monchoman45

+0

No funcionó cuando intenté usar 'delete xhr.onreadystatechange', cambiarlo a' xhr.onreadystatechange = null' funcionó bien. –

+0

He editado el código para usar '= null' en lugar de' eliminar' –

0

nunca he tenido mi manejador onreadystatechange ejecuta varias veces con un readyState de 4.

Creo asumiendo una sola ejecución en DONE es correcta.

+1

bien, no tengo. Es bastante fácil de reproducir: http://jsfiddle.net/44b3P/ – qbolec

+0

Solo aparece una alerta cada vez que recargo la página, lo siento. (último Chrome) –

+0

El problema es SOLAMENTE en modo de depuración (lo probé solo en Mac). Debe abrir las Herramientas de desarrollo y luego volver a cargar la página. Tampoco es "determinista" (para el usuario), ya que a veces (rara vez) no sucede. Tampoco pude entender la lógica sobre cuántas veces se llama. –