J'aimerais savoir s'il est possible de "raccorder" à chaque demande AJAX (soit sur le point d'être envoyé, soit lors d'événements)) et d'effectuer une action. À ce stade, je m en supposant que la page contient d'autres scripts tiers, dont certains peuvent utiliser jQuery, d'autres pas. Est-ce possible?
Inspiré par réponse d’aviv , j’ai mené une petite enquête et c’est ce que j’ai trouvé.
Je ne suis pas sûr que ce soit si utile que selon les commentaires du script et bien sûr ne fonctionnera que pour les navigateurs utilisant un objet XMLHttpRequest natif .
Je pense que cela fonctionnera si les bibliothèques javascript sont utilisées, car elles utiliseront l’objet natif si possible.
function addXMLRequestCallback(callback){
var oldSend, i;
if( XMLHttpRequest.callbacks ) {
// we've already overridden send() so just add the callback
XMLHttpRequest.callbacks.Push( callback );
} else {
// create a callback queue
XMLHttpRequest.callbacks = [callback];
// store the native send()
oldSend = XMLHttpRequest.prototype.send;
// override the native send()
XMLHttpRequest.prototype.send = function(){
// process the callback queue
// the xhr instance is passed into each callback but seems pretty useless
// you can't tell what its destination is or call abort() without an error
// so only really good for logging that a request has happened
// I could be wrong, I hope so...
// EDIT: I suppose you could override the onreadystatechange handler though
for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
XMLHttpRequest.callbacks[i]( this );
}
// call the native send()
oldSend.apply(this, arguments);
}
}
}
// e.g.
addXMLRequestCallback( function( xhr ) {
console.log( xhr.responseText ); // (an empty string)
});
addXMLRequestCallback( function( xhr ) {
console.dir( xhr ); // have a look if there is anything useful here
});
REMARQUE: La réponse acceptée ne produit pas la réponse car elle est appelée trop tôt.
Vous pouvez faire cela en interceptant génériquement n'importe quel AJAX globalement et sans foirer les callbacks etc. qui ont peut-être été attribué par un tiers AJAX bibliothèques.
(function() {
var origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
console.log('request started!');
this.addEventListener('load', function() {
console.log('request completed!');
console.log(this.readyState); //will always be 4 (ajax is completed successfully)
console.log(this.responseText); //whatever the response was
});
origOpen.apply(this, arguments);
};
})();
Quelques autres documents sur ce que vous pouvez faire ici avec l’API addEventListener ici:
(Notez que cela ne fonctionne pas <= IE8)
Puisque vous parlez de jquery, je sais que jquery propose une méthode .ajaxSetup()
qui définit des options ajax globales incluant les déclencheurs d'événements tels que success
, error
et beforeSend
. - ce qui ressemble à ce que vous recherchez.
$.ajaxSetup({
beforeSend: function() {
//do stuff before request fires
}
});
bien entendu, vous devez vérifier la disponibilité de jQuery sur toutes les pages sur lesquelles vous essayez d'utiliser cette solution.
Il y a une astuce pour le faire.
Avant que tous les scripts soient exécutés, prenez l'objet XHMHttpReuqest d'origine et enregistrez-le dans une autre variable. Puis substituez le XMLHttpRequest d'origine et dirigez tous les appels vers ce dernier via votre propre objet.
Code Psuedo:
var savd = XMLHttpRequest;
XMLHttpRequest.prototype = function() {
this.init = function() {
}; // your code
etc' etc'
};
J'ai trouvé une bonne bibliothèque sur Github qui fait le travail bien, vous devez l'inclure avant tout autre fichier js
https://github.com/jpillora/xhook
voici un exemple qui ajoute un en-tête http à toute réponse entrante
xhook.after(function(request, response) {
response.headers['Foo'] = 'Bar';
});
En utilisant la réponse de "meouw", je suggère d'utiliser la solution suivante si vous voulez voir les résultats de la requête
function addXMLRequestCallback(callback) {
var oldSend, i;
if( XMLHttpRequest.callbacks ) {
// we've already overridden send() so just add the callback
XMLHttpRequest.callbacks.Push( callback );
} else {
// create a callback queue
XMLHttpRequest.callbacks = [callback];
// store the native send()
oldSend = XMLHttpRequest.prototype.send;
// override the native send()
XMLHttpRequest.prototype.send = function() {
// call the native send()
oldSend.apply(this, arguments);
this.onreadystatechange = function ( progress ) {
for( i = 0; i < XMLHttpRequest.callbacks.length; i++ ) {
XMLHttpRequest.callbacks[i]( progress );
}
};
}
}
}
addXMLRequestCallback( function( progress ) {
if (typeof progress.srcElement.responseText != 'undefined' && progress.srcElement.responseText != '') {
console.log( progress.srcElement.responseText.length );
}
});
jquery ...
<script>
$(document).ajaxSuccess(
function(event, xhr, settings){
alert(xhr.responseText);
}
);
</script>
En plus de la réponse meouw, j'ai dû injecter du code dans un iframe qui intercepte les appels XHR et a utilisé la réponse ci-dessus. Cependant, je devais changer
XMLHttpRequest.prototype.send = function(){
À:
XMLHttpRequest.prototype.send = function(arguments)
Et je devais changer
oldSend.apply(this, arguments);
À:
oldSend.call(this, arguments);
Cela était nécessaire pour que cela fonctionne dans IE9 avec le mode document IE8 . Si cette modification n'était pas apportée, certains rappels générés par la structure de composant (Visual WebGUI) ne fonctionnaient pas. Plus d'infos sur ces liens:
Sans ces modifications AJAX les publications) ne se sont pas terminées.
Ajax-hook est une bibliothèque open source pour accrocher un objet XMLHttpRequest global et modifie la demande et la réponse Ajax par défaut. github: https://github.com/wendux/Ajax-hook , par exemple:
hookAjax({
//hook callbacks
onreadystatechange:function(xhr){
console.log("onreadystatechange called: %O",xhr)
},
onload:function(xhr){
console.log("onload called: %O",xhr)
},
//hook function
open:function(arg,xhr){
console.log("open called: method:%s,url:%s,async:%s",arg[0],arg[1],arg[2])
}
})