2012-10-06 12 views
5

W3C spec Proponuję następujący realizacji: Niektóre prosty kod coś zrobić z danymi z dokumentu XML idącą przez sieć:Czy wyzwalacz XHR może się uruchamiać kilkakrotnie z 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(); 

Czy ta implementacja naprawdę poprawna?

Podczas debugowania Znalazłem przypadki, gdy readystatechanged obsługi zdarzeń jest wywoływana częściej niż raz z rzędu o tej samej wartości readyState == 4. Myślę, że to zachowanie jest poprawne, jak specyfikacje mówi, że każda zmiana stanu musi odpalić zdarzenie, i to, że parametr readyState musi zawsze być równy bieżącemu, więc jeśli w kolejce zdarzeń pojawi się kilka zdarzeń, jest oczywiste, że jeden otrzyma wiele połączeń z readyState == 4.

http://jsfiddle.net/44b3P/ - to jest powyżej przykład rozszerzony o wywołanie debuggera, aby wstrzymać wykonywanie zaraz po wysłaniu żądania, oraz z alertem() w processData. Po wznowieniu wykonania otrzymasz 3 alerty.

Ten przykład z w3c wydaje się być kopiowany & wklejony w wielu miejscach w Internecie - w szczególności OpenSocial wydaje się obsługiwać zdarzenia XHR w ten sposób. Czy to jest poprawne?

Odpowiedz

11

Widziałem również to samo zachowanie (DONE 200 zostało trafione więcej niż raz, tj. 2 ... n razy) podczas debugowania w Narzędziach dla programistów w przeglądarce Chrome.

Aby to działa zawsze w trybie debugowania, a także, znalazłem dwie opcje:

  1. Wpisz onload zweryfikować powodzenie w XMLHTMLRequest W3C Spec

    client.onload = handler;

    Ta wersja nie będzie działać w IE8. To musi być przeglądarką, która implementuje interfejs XMLHttpRequestEventTarget

  2. Zdjąć obsługi onreadystatechange jak tylko masz DONE 200 stan.

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

Mam również otwarty problem w Chromium tego problemu, podając Fiddle (dzięki!)

+1

Podobnie jak dodatek - przy użyciu pierwotnie podanego kodu, 'this.onreadystatechange = null;' jest wystarczające, nie potrzebujesz oryginalnego odniesienia do XHR ('client'). – Monchoman45

+0

Nie działało, gdy próbowałem używać 'delete xhr.onreadystatechange', zmiana na' xhr.onreadystatechange = null' działała dobrze. –

+0

Edytowałem kod, aby użyć '= null' zamiast' delete' –

0

Nigdy nie miałem mój onreadystatechange obsługi wykonywane wielokrotnie z readyState od 4.

myślę zakładając pojedynczy wykonanie Done jest poprawna.

+1

dobrze, mam. Jest to dość łatwe do odtworzenia: http://jsfiddle.net/44b3P/ – qbolec

+0

Tylko jeden alert pojawia się za każdym razem, gdy przeładowuję stronę, przepraszam. (najnowszy Chrome) –

+0

Problem jest TYLKO w trybie debugowania (testowałem go tylko na komputerze Mac). Musisz otworzyć Narzędzia dla programistów, a następnie ponownie załadować stronę. Nie jest też "deterministyczny" (dla użytkownika), ponieważ czasami (rzadko) się nie zdarza. Nie mogłem też zrozumieć logiki, ile razy jest wywoływana. –

Powiązane problemy