web-dev-qa-db-fra.com

Comment puis-je tirer parti des fonctions de rappel pour XMLHttpRequest asynchrone?

Je suis en train d'écrire JavaScript et déroutant au sujet de callback . J'ai trouvé qu'il ne s'agissait pas de fonctions intégrées ...
Je lis maintenant O'Relly JavaScript 5th Edition et il montre un exemple de code ressemblant à ceci:

getText = function(url, callback) // How can I use this callback?
{
    var request = new XMLHttpRequest();
    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            callback(request.responseText); // Another callback here
        }
    }
    request.open('GET', url);
    request.send();
}

Fondamentalement, je suppose que je ne comprends pas l’idée générale de callback cependant ... Quelqu'un pourrait-il écrire un exemple de code pour tirer parti de callback ci-dessus?

20
Japboy

Les rappels sont assez simples et astucieux! En raison de la nature des appels AJAX, vous ne [] bloquez pas l'exécution de votre script jusqu'à ce que votre demande soit terminée (ce serait alors synchrone). Un rappel est simplement une méthode désignée pour gérer la réponse une fois que celle-ci est retournée à votre méthode. 

Les méthodes javascript étant des objets de première classe, vous pouvez les transmettre comme des variables.

Donc dans votre exemple 

getText = function(url, callback) // How can I use this callback?
{
    var request = new XMLHttpRequest();
    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            callback(request.responseText); // Another callback here
        }
    }; 
    request.open('GET', url);
    request.send();
}

function mycallback(data) {
   alert(data);
}

getText('somephpfile.php', mycallback); //passing mycallback as a method

Si vous procédez comme indiqué ci-dessus, cela signifie que vous passez mycallback comme méthode qui gère votre réponse (rappel).

MODIFIER

Bien que l'exemple présenté n'illustre pas les avantages d'un rappel (vous pouvez simplement placer l'alerte dans la fonction onReadyStateChange!), La convivialité est certainement un facteur. 

Il ne faut pas oublier que l'important est que les méthodes JS soient des objets de première classe. Cela signifie que vous pouvez les transmettre comme des objets et les attacher à toutes sortes d'événements. Lorsque des événements se déclenchent, les méthodes attachées à ces événements sont appelées. 

Lorsque vous exécutez request.onreadystatechange = function(){}, vous assignez simplement cette méthode à l'appel lorsque l'événement approprié est déclenché. 

La chose intéressante ici est que ces méthodes peuvent être réutilisées. Supposons que vous disposiez d'une méthode de traitement des erreurs qui affiche une alerte et remplit certains champs de la page HTML dans le cas d'un 404 dans la demande AJAX. 

Si vous ne parvenez pas à affecter des callbacks ou à passer des méthodes en tant que paramètres, vous devrez écrire le code de traitement des erreurs encore et encore, mais il vous suffira simplement de l'affecter en tant que rappel et tout traitement de vos erreurs sera trié. en une fois. 


44
JohnP

Tout d'abord, je suggérerais de lire ce qu'est un rappel. Ici est un début.

La grande image

Les rappels sont largement utilisés dans la programmation asynchrone. Lorsque vous ne souhaitez pas bloquer jusqu'à la fin d'une opération (éventuellement) longue, l'une des façons de résoudre le problème consiste à déléguer l'opération à une personne qui le fera pour vous. Cela soulève la question: comment saurez-vous que l'opération est terminée et comment obtiendrez-vous ses résultats?

Une solution consisterait à déléguer le travail à quelqu'un d'autre et à prendre un moment de votre travail habituel de temps en temps pour demander "le travail que je vous ai fait a-t-il déjà fait?" Si c'est le cas, obtenez les résultats d'une manière ou d'une autre et c'est parti. Problème résolu.

Le problème avec cette approche est que cela ne vous rend pas la vie beaucoup plus facile. Vous êtes maintenant obligé de demander tout le temps et vous ne saurez pas que l'opération est faite dès qu'elle est réellement (mais seulement la prochaine fois que vous vous souviendrez de demander). Si vous oubliez de demander, vous serez jamais informé.

Le callback est une meilleure solution: lorsque vous déléguez du travail, indiquez-lui une fonction. Le code qui va réellement faire le travail promet alors d'appeler cette fonction dès la fin du travail. Vous pouvez maintenant tout oublier et vous assurer que, lorsque le travail sera terminé, votre rappel sera appelé. Pas plus tôt et pas plus tard.

Quel est le rappel ici?

Dans ce cas particulier, callback est une fonction que vous fournissez à getText afin de lui permettre de communiquer avec vous. Vous dites en effet "faites ce travail pour moi, et lorsque vous aurez terminé, voici une fonction que vous pourrez appeler pour me le faire savoir".

getText choisit en fait d’utiliser ce rappel uniquement lorsque la XMLHttpRequest (XHR) est complétée, et en même temps, il vous "fait savoir" qu'il vous transmet également le contenu de la réponse HTTP (pour que vous puissiez agir sur ces informations).

Rappels et plus de rappels, oh mon dieu!

Mais prenez un autre moment pour lire le code. Quelle est la valeur qu'il stocke dans request.onreadystatechange? Quel est le but de request.onreadystatechange?

La réponse est que request.onreadystatechange est là pour vous permettre de remplir avec un rappel. En effet, XHR vous donne le moyen de lui envoyer un rappel et vous promet de vous "rappeler" chaque fois que l'état de la requête HTTP sous-jacente change.

getText est une fonction qui construit une abstraction en plus de cela}: elle branche son propre rappel (une fonction anonyme - je l'appellerai comme "interne") et accepte un autre callback de votre part (le paramètre - je l'appellerai "externe"). Lorsque le rappel interne (qui, rappelez-vous: est appelé chaque fois que l'état change) détecte que l'état est "terminé" (signification de la valeur 4) et que le code d'état de la réponse HTTP est 200 (ce qui signifie "OK"), il appelle le rappel externe pour vous informer, en tant qu'utilisateur de getText, du résultat.

J'espère avoir du sens. :)

17
Jon

Personnellement, je préfère utiliser Event Listener plutôt que des rappels.

L'utilisation de Listeners est particulièrement utile lorsque vous êtes prêt à traiter plusieurs demandes asynchrones à la fois.

L’utilisation est la suivante (extrait de https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest )

function reqListener () {
  console.log(this.responseText);
}

var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://www.example.org/example.txt");
oReq.send()
1
Mikolas Pansky

Ce qui fonctionne correctement est de définir un service qui renvoie une telle promesse!

$http.head("url2check").then(function () {
                return true;
            }, function () {
                return false;
            });

Dans le contrôleur, utilisez le service:

<service>.<service method>.then(function (found)) {
     if (found) {......
}

@jon a raison d'appeler cela asynchrone! 

0
Sydwell