Ajouter un" crochet " à toutes les requêtes AJAX sur une page
j'aimerais savoir s'il est possible de" hook " dans chaque requête AJAX (que ce soit sur le point d'être envoyée, ou sur des événements) et d'effectuer une action. À ce stade, je suppose qu'il y a d'Autres scripts tiers sur la page. Certains peuvent utiliser jQuery, tandis que d'autres ne le font pas. Est-ce possible?
9 réponses
inspiré par réponse d'aviv , j'ai fait une petite enquête et c'est ce que j'ai trouvé.
Je ne suis pas sûr que ce soit tout ce que utile selon les commentaires dans le script et bien sûr ne fonctionnera que pour les navigateurs utilisant un objet xmltprequest 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
});
si vous n'avez pas à supporter <= IE8, vous pouvez faire cela qui interceptera de manière générique n'importe quel AJAX globalement et ne ratera aucun callbacks etc. qui peut-être ont été assignés par des bibliothèques AJAX tierces. La réponse acceptée ne donne pas la réponse réelle parce qu'elle est appelée trop tôt.
(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);
};
})();
un peu plus de docs de ce que vous pouvez faire ici avec l'API addEventListener ici:
puisque vous mentionnez jquery, je sais que jquery offre une méthode .ajaxSetup()
qui définit des options ajax globales qui incluent les déclencheurs d'événements comme success
, error
, et beforeSend
- qui est ce qui ressemble à ce que vous recherchez.
$.ajaxSetup({
beforeSend: function() {
//do stuff before request fires
}
});
bien sûr, vous auriez besoin de vérifier la disponibilité de jQuery sur toute page que vous essayez d'utiliser cette solution sur.
il y a un truc pour le faire.
avant d'exécuter tous les scripts, prenez L'objet XHMHttpReuqest original et sauvegardez-le dans un var différent. Ensuite, outrepassez la requête XMLHttpRequest originale et dirigez tous les appels vers celle-ci 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 tous les autres fichiers js
https://github.com/jpillora/xhook
voici un exemple qui ajoute un en-tête http à n'importe quelle 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 demande
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 de meouw, j'ai dû injecter du code dans une iframe qui intercepte les appels XHR, et j'ai utilisé la réponse ci-dessus. Cependant, j'ai dû changer
XMLHttpRequest.prototype.send = function(){
à:
XMLHttpRequest.prototype.send = function(arguments)
et j'ai dû changer
oldSend.apply(this, arguments);
à:
oldSend.call(this, arguments);
cela était nécessaire pour obtenir le fonctionnement dans IE9 avec mode de document IE8 . Si cette modification n'a pas été faite, certains les rappels générés par le framework component (Visual WebGUI) n'ont pas fonctionné. Plus d'informations sur ces liens:
sans ces modifications AJAX postbacks n'a pas pris fin.
Ajax-hook est un lib open source pour hook global XMLHttpRequest object, et change la requête Ajax par défaut et la réponse . github: https://github.com/wendux/Ajax-hook 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])
}
})