2010-07-22 3 views
4

Je suis récemment en train de batifoler avec quelques techniques d'interrogation ajax. Cependant, il semble que je ne puisse pas écraser le gestionnaire onreadystatechange d'un objet XMLHttpRequest dans FireFox (3.6.7).jQuery Ajax, remplace le gestionnaire onreadystatechange

En dépistant le problème pourquoi FF lève une exception en essayant d'accéder à onreadystatechange, j'ai réalisé que cela dépend si la méthode send() a été appelée ou non.

En d'autres termes, voici un exemple (js plaine, pas jQuery jusqu'à présent), qui fonctionne:

(Ceci est assez simplifié juste pour une démonstration)

var myxhr = new XMLHttpRequest(); 
myxhr.open("GET", "/my/index.php"); 
myxhr.onreadystatechange = function(){ 
    console.log('ready state changed'); 
}; 
console.log("onreadystatechange function: ", myxhr.onreadystatechange); 
myxhr.send(null); 

Cela fonctionne, mieux dit qu'il est possible d'accéder myxhr.onreadystatechange ici. Si je change les deux dernières lignes de code, FF lance une exception, en me disant que je ne suis pas autorisé à accéder à cet objet.

myxhr.send(null); 
console.log("onreadystatechange function: ", myxhr.onreadystatechange); 

Echoue.

Alors où est mon problème actuel? Je souhaite utiliser $.ajax() de jQuery. Mais si j'essaie d'écraser la méthode onreadystatechange d'un objet XHR qui a été renvoyé par $.ajax(), je reçois la même exception FireFox.

Ok Je ai déjà trouvé pourquoi cela se produit, donc j'ai pensé à propos de, hui qu'en est-il de la propriété beforeSend de $.ajax()? Donc j'ai fondamentalement essayé ceci:

var myxhr = $.ajax({ 
    url:  "/my/index.php", 
    type:  "GET", 
    dataType: "text", 
    data:  { 
     foo: "1" 
    }, 
    beforeSend: function(xhr){ 
     var readystatehook = xhr.onreadystatechange; 

     xhr.onreadystatechange = function(){ 
      readystatehook.apply(this, []); 
      console.log('fired'); 
     }; 
    }, 
    success: function(data){ 
     console.log(data); 
    }, 
    error:  function(xhr, textStatus, error){ 
     console.log(xhr.statusText, textStatus, error); 
    } 
}); 

Devinez quoi, FireFox lève une exception. Alors, qu'est-ce que vous faites maintenant? Vous creusez dans la source jQuery, comme je l'ai fait. Mais cela a apporté plus de questions que de réponses en réalité. Il semble que beforeSend() soit appelé avant que xhr.send() soit exécuté. Donc, je me demande pourquoi, sur Terre, FireFox ne permet pas d'écraser le gestionnaire à ce stade.

Conclusion?

Il est impossible de créer un custom readystatechange handler avec jQuery/Firefox?

Répondre

2

Je suis d'accord avec Maz ici, vous pouvez toujours bénéficier former le traitement des requêtes et la création de l'objet, et pas non plus besoin de patcher jquery pour cette

cependant, si vous ne vous dérange pas patcher jquery vous pouvez ajouter ces lignes

 // The readystate 2 
     } else if (!requestDone && xhr && xhr.readyState === 2 && isTimeout !== 'timeout' && s.state2) { 
      s.state2.call(s.context, data, status, xhr); 
     // The readystate 3 
     } else if (!requestDone && xhr && xhr.readyState === 3 && isTimeout !== 'timeout' && s.state3) { 
      s.state3.call(s.context, data, status, xhr); 

avant cette ligne: (jQuery v 1.4.4) ou rechercher juste pour le readyState === 4 dans la source

 // The transfer is complete and the data is available, or the request timed out 
     } else if (!requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout")) { 

maintenant, vous pouvez utiliser le .ajax $ à nouveau et mettre un gestionnaire pour état2 et STATE3 comme ceci:

$.ajax({ 
    url: 'http://www.stackoverflow.com', 
    cache: false, 
    success:function(){console.log('success');}, 
    error: function(){console.log('error');}, 
    complete: function(){console.log('complete');}, 
    state2: function (context,data,status,xhr) {console.log('state2');}, 
    state3: function (context,data,status,xhr) {console.log('state3');} 
}); 

il ne se comporte pas exactement comme les autres gestionnaires, par exemple returngin false ne fera rien mais vous pouvez toujours manipuler l'objet xhr et annuler de cette façon

voir si je peux soumettre ceci pour être inclus dans la source plus tard dans la journée, qui sait qu'ils pourraient l'accepter

1

Si vous voulez un grand niveau de personnalisation, vous pouvez simplement obtenir l'objet XMLHttpRequest et le contrôler vous-même.

var x=new $.ajaxSettings.xhr(); 
x.onreadystatechange=function(){ ... } 
... 
+0

l'appel de $ .ajax() 'après cet appel semble écraser cet objet' xhr'. ? Pouvez-vous ajouter un exemple de comment ajouter un gestionnaire 'readystate 'personnalisé appelant jQuerys' $ .ajax() '? – jAndy

+1

JQuery devrait l'accepter comme paramètre, ce qu'il choisit de ne pas faire. Si vous voulez ce niveau de personnalisation, vous devez manipuler directement l'objet XmlHttpRequest. – Maz

0

Vous pouvez le faire en faisant quelque chose comme ça:

$.ajax({ 
type: "POST", 
url: "Test.ashx", 
data: { "command": "test" }, 
contentType: "application/x-www-form-urlencoded; charset=utf-8", 
dataType: "json", 
beforeSend: function (request, settings) { 
    $(request).bind("readystatechange", function (e) { alert("changed " + e.target.readyState); }); 
}}); 
+0

Était-ce encore testé? Cela ne fonctionne probablement pas. – vangheem

+4

Oui, il a été testé et fonctionne. En outre, vous devriez le tester avant de laisser des commentaires comme ça. – Vinicius

+0

Je l'ai fait, ça ne marche pas. – vangheem

Questions connexes