Comment puis-je retourner la réponse d'un appel asynchrone?
J'ai une fonction foo
qui fait une requête Ajax. Comment puis-je retourner la réponse de foo
?
J'ai essayé de retourner la valeur de la success
de rappel ainsi que de l'affectation de la réponse à une variable locale à l'intérieur de la fonction, et retourner celui-là, mais aucun de ces moyens fait de retourner la réponse.
function foo() {
var result;
$.ajax({
url: '...',
success: function(response) {
result = response;
//return response; //<- I tried that one as well
}
});
return result;
}
var result = foo(); //It always ends up being `undefined`.
Pour une simple intro de Promesses, cela peut être une bonne lecture: devopedia.org/promises
[J'ai été confrontée au même problème de l'appel asynchrone à l'aide d'axios et js, mais il n'est pas recommandé d'utiliser une fonction synchrone, cela fonctionne pour certaines situations. ](stackoverflow.com/questions/55239719/...)
Vous ne pouvez pas le faire fonctionner de la façon dont vous le souhaitez. si async/await serait de travailler. là encore, c'est la promesse base
[J'ai été confrontée au même problème de l'appel asynchrone à l'aide d'axios et js, mais il n'est pas recommandé d'utiliser une fonction synchrone, cela fonctionne pour certaines situations. ](stackoverflow.com/questions/55239719/...)
Vous ne pouvez pas le faire fonctionner de la façon dont vous le souhaitez. si async/await serait de travailler. là encore, c'est la promesse base
OriginalL'auteur Felix Kling | 2013-01-08
Vous devez vous connecter pour publier un commentaire.
Le problème
La Un dans Ajax signifie asynchrone . Cela signifie que l'envoi de la demande (ou plutôt de la réception de la réponse) est retiré du flux d'exécution normale. Dans votre exemple,
$.ajax
renvoie immédiatement et l'instruction suivante,return result;
, est exécutée avant que la fonction que vous avez passé commesuccess
de rappel a même appelé.Voici une analogie qui je l'espère rend la différence entre synchrone et asynchrone flux plus clair:
Synchrone
Imaginez-vous faire un appel téléphonique à un ami et demandez-lui de chercher quelque chose pour vous. Bien qu'il pourrait prendre un certain temps, vous attendez sur le téléphone et regarder dans l'espace, jusqu'à ce que votre ami vous donne la réponse que vous avez besoin.
La même chose qui se passe quand vous faites un appel de fonction contenant "normal" code:
Même si
findItem
peut prendre beaucoup de temps pour exécuter n'importe quel code à venir aprèsvar item = findItem();
a pour attendre jusqu'à ce que la fonction renvoie le résultat.Asynchrone
Vous appelez votre ami de nouveau pour la même raison. Mais cette fois, vous lui dites que vous êtes pressé et il devrait vous rappeler sur votre téléphone mobile. Vous raccrochez, quitter la maison et faire ce que vous aviez prévu de faire. Une fois que votre ami vous appelle en arrière, vous avez affaire avec les informations qu'il vous a donné.
C'est exactement ce qui se passe quand vous faites une requête Ajax.
Au lieu d'attendre la réponse, l'exécution se poursuit immédiatement et l'instruction suivant l'appel Ajax est exécutée. Pour obtenir la réponse par la suite, vous fournir une fonction qui doit être appelée une fois la réponse reçue, un rappel (remarquez quelque chose? de retour d'appel ?). Toute déclaration vient après que l'appel est exécuté avant le callback est appelée.
Solution(s)
Embrasser la nature asynchrone de JavaScript! Alors que certaines opérations asynchrones fournir synchrone homologues (ne sorte de "Ajax"), il est généralement déconseillé de les utiliser, surtout dans un contexte du navigateur.
Pourquoi est-il mauvais demandez-vous?
JavaScript s'exécute dans le thread de l'INTERFACE utilisateur du navigateur et un long processus en cours d'exécution de verrouillage de l'INTERFACE utilisateur, le rendant insensible. En outre, il existe une limite supérieure sur le temps d'exécution de JavaScript et le navigateur va demander à l'utilisateur s'il veut continuer l'exécution ou non.
Tout cela, c'est vraiment de la mauvaise expérience de l'utilisateur. L'utilisateur ne sera pas en mesure de dire si tout fonctionne bien ou pas. En outre, l'effet sera pire pour les utilisateurs avec une connexion lente.
Dans ce qui suit, nous étudierons trois solutions différentes qui sont tous les uns sur les autres:
async/await
(ES2017+, disponible dans les navigateurs plus anciens si vous utilisez un transpiler ou régénérateur)then()
(ES2015+, disponible dans les navigateurs plus anciens si vous utilisez l'un des nombreux promesse bibliothèques)Tous les trois sont disponibles dans les navigateurs actuels, et le nœud 7+.
ES2017+: des Promesses de
async/await
ECMAScript version publiée en 2017 introduit de syntaxe au niveau de l'appui asynchrones fonctions. Avec l'aide de
async
etawait
, vous pouvez écrire asynchrone dans un "synchrone". Le code est encore asynchrone, mais c'est plus facile à lire/comprendre.async/await
s'appuie sur les promesses: uneasync
fonction renvoie toujours une promesse.await
"déballe" une promesse et soit à la valeur de la promesse a été résolu avec ou renvoie une erreur si la promesse a été rejetée.Important: Vous ne pouvez utiliser
await
à l'intérieur d'unasync
fonction. Droit maintenant de haut niveau,await
n'est pas encore pris en charge, de sorte que vous pourriez avoir à faire un async IIFE (Immédiatement Appelé La Fonction D'Expression) pour démarrer uneasync
contexte.Vous pouvez en lire plus à propos de
async
etattendre
sur MDN.Voici un exemple qui s'appuie sur le dessus de retard ci-dessus:
Actuel navigateur et nœud prise en charge des versions
async/await
. Vous pouvez également en charge les anciens environnements en transformant votre code de ES5 avec l'aide de régénérateur (ou l'utilisation d'outils de régénérateur, comme Babel).Laisser fonctions acceptent rappels
Un rappel est simplement passé à une autre fonction. Cette autre fonction peut appeler la fonction transmise à chaque fois que c'est prêt. Dans le contexte d'un processus asynchrone, le callback sera appelé à chaque fois que le processus asynchrone est fait. Généralement, le résultat est transmis à la fonction de rappel.
Dans l'exemple de la question, vous pouvez faire
foo
accepter un rappel et l'utiliser commesuccess
de rappel. Donc, cedevient
Ici, nous avons défini la fonction "inline", mais vous pouvez passer à n'importe quelle fonction de référence:
foo
elle-même est définie comme suit:callback
fera référence à la fonction, nous passons àfoo
quand nous l'appelons et nous avons simplement transmettre àsuccess
. I. e. une fois la requête Ajax est un succès,$.ajax
appelleracallback
et passer la réponse à la fonction de rappel (qui peut être appelée avecresult
, puisque c'est de cette façon que nous avons défini la fonction de rappel).Vous pouvez également traiter la réponse avant de passer à la fonction de rappel:
Il est plus facile d'écrire du code à l'aide de rappels que cela puisse paraître. Après tout, JavaScript dans le navigateur est largement piloté par les événements (événements DOM). La réception de l'Ajax réponse est rien d'autre, mais d'un événement.
Des difficultés peuvent survenir lorsque vous avez à travailler avec de la troisième partie du code, mais la plupart des problèmes peuvent être résolus par la seule pensée de par le flux de l'application.
ES2015+: des Promesses de alors()
La La promesse de l'API est une nouvelle fonctionnalité d'ECMAScript 6 (ES2015), mais il a de bonnes prise en charge du navigateur déjà. Il y a aussi beaucoup de bibliothèques qui mettent en œuvre la norme Promesses de l'API et de fournir de nouvelles méthodes pour faciliter l'utilisation et la composition de fonctions asynchrones (par exemple bluebird).
Promesses sont des conteneurs pour avenir valeurs. Lorsque la promesse reçoit la valeur (c'est résolu) ou lorsqu'il est annulé (rejeté), il en informe l'ensemble de ses "auditeurs" qui veulent accéder à cette valeur.
L'avantage par rapport à la plaine des rappels, c'est qu'ils vous permettent de découpler le code, et ils sont plus faciles à composer.
Voici un exemple simple de l'utilisation d'une promesse:
Appliqué à notre appel Ajax nous pourrions utiliser des promesses comme ceci:
Décrivant tous les avantages que la promesse offre est au-delà de la portée de cette réponse, mais si vous écrivez le nouveau code, vous devriez sérieusement considérer. Ils fournissent une grande abstraction et de la séparation de votre code.
Plus d'informations sur les promesses: HTML5 rocks - JavaScript Promesses
Note de côté: jQuery différée des objets
Différés objets sont jQuery personnalisée de la mise en œuvre des promesses (avant que la Promesse de l'API a été normalisé). Ils se comportent presque comme des promesses, mais d'exposer un peu différente de l'API.
Chaque méthode Ajax de jQuery retourne déjà un différée "objet" (en fait, une promesse d'un différé d'objet) que vous pouvez juste retour de votre fonction:
Note de côté: la Promesse de pièges
Garder à l'esprit que les promesses et différés objets conteneurs pour une valeur d'avenir, ils ne sont pas la valeur elle-même. Par exemple, supposons que vous avez eu la suivante:
Ce code ne comprend pas le au-dessus de l'asynchronie des questions. Plus précisément,
$.ajax()
ne gèle pas le code alors qu'il vérifie l' '/mot de passe " à la page sur votre serveur, il envoie une requête au serveur et pendant qu'il attend, renvoie immédiatement un jQuery Ajax Différée objet, pas la réponse du serveur. Cela signifie que leif
déclaration va toujours obtenir ce Différé de l'objet, de le traiter commetrue
, et agir comme si l'utilisateur est connecté. Pas bonne.Mais la solution est facile:
Pas recommandé: Synchrone "Ajax" appels
Comme je l'ai mentionné, certains(!) les opérations asynchrones ont synchrone homologues. Je ne défends pas leur utilisation, mais à des fins d'exhaustivité, voici comment vous pourriez effectuer un appel synchrone:
Sans jQuery
Si vous utilisez directement un
XMLHTTPRequest
objet, passerfalse
comme troisième argument de.ouvrir
.jQuery
Si vous utilisez jQuery, vous pouvez définir la
async
option pourfalse
. Notez que cette option est obsolète depuis jQuery 1.8.Vous pouvez alors soit utiliser toujours une
success
de rappel ou d'accéder à l'responseText
propriété de la jqXHR objet:Si vous utilisez tout autre jQuery Ajax méthode, telle que
$.get
,$.getJSON
, etc., vous devez le modifier pour$.ajax
(puisque vous ne pouvez passer des paramètres de configuration pour$.ajax
).Heads up! Il n'est pas possible de faire un synchrones JSONP demande. JSONP, par sa nature, est toujours asynchrone (une raison de plus pour ne même pas envisager cette option).
Dans la Solution 1, sous jQuery, je ne pouvais pas comprendre cette ligne:
If you use any other jQuery AJAX method, such as $.get, $.getJSON, etc., you have them to $.ajax.
(Oui, je me rends compte que mon pseudo est un peu ironique de constater dans ce cas)Mmmh, je ne sais pas comment il peut être rendu plus clair. Voyez-vous comment
foo
est appelé, et une fonction est passée (foo(function(result) {....});
)?result
est utilisé à l'intérieur de cette fonction et est la réponse de la requête Ajax. Pour se référer à cette fonction, le premier paramètre de foo est appelécallback
et affecté àsuccess
au lieu d'une fonction anonyme. Donc,$.ajax
appelleracallback
lorsque la demande a été couronnée de succès. J'ai essayé d'expliquer un peu plus.Le Chat, pour cette question, est mort donc je ne suis pas sûr de l'endroit où à proposer décrit les changements, mais je propose: 1) Changement de la partie synchrone à une simple discussion de pourquoi c'est mauvais sans le code d'exemple de comment le faire. 2) Supprimer/fusionner le rappel des exemples d'afficher uniquement les plus flexibles Différés approche, qui, je pense, peut aussi être un peu plus facile à suivre pour ceux qui souhaitent apprendre le Javascript.
Je pense que vous avez mal compris la partie de la réponse. Vous ne pouvez pas utiliser
$.getJSON
si vous voulez de la requête Ajax synchrone. Cependant, vous ne devriez pas l'événement voulez à la demande pour être synchrones, ce qui ne s'applique pas. Vous devriez être en utilisant des rappels ou des promesses pour gérer la réponse, comme il est expliqué plus haut dans la réponse.OriginalL'auteur Felix Kling
Si vous êtes pas à l'aide de jQuery dans votre code, cette réponse est pour vous
Votre code doit être quelque chose le long des lignes de ce:
Felix Kling fait un excellent travail de l'écriture d'une réponse pour les personnes à l'aide de jQuery, AJAX, j'ai décidé d'offrir une alternative pour les personnes qui ne le sont pas.
(Remarque, pour ceux qui utilisent le nouveau
fetch
API, Angulaire ou promesses, j'ai ajouté une autre réponse ci-dessous)Ce que vous êtes confronté à
C'est un court résumé de "l'Explication du problème" de l'autre réponse, si vous n'êtes pas sûr après cette lecture, lire.
La Un en AJAX signifie asynchrone. Cela signifie que l'envoi de la demande (ou plutôt de la réception de la réponse) est retiré du flux d'exécution normale. Dans votre exemple,
.envoyer
renvoie immédiatement et l'instruction suivante,return result;
, est exécutée avant que la fonction que vous avez passé commesuccess
de rappel a même appelé.Cela signifie que lorsque vous êtes de retour, l'auditeur vous avez défini ne s'est pas exécuté, ce qui signifie que la valeur que vous êtes de retour n'a pas été défini.
Ici est une simple analogie
(Fiddle)
La valeur de
a
retournée estundefined
depuis lea=5
partie n'a pas exécuté. AJAX des actes comme cela, vous êtes de retour à la valeur avant que le serveur a eu la chance de dire à votre navigateur ce que la valeur des autres.Une solution possible à ce problème est de code re-activement , en parler à votre programme de quoi faire une fois le calcul terminé.
Ce qui est appelé CPS. Fondamentalement, nous sommes de passage
getFive
une action à effectuer lorsqu'elle est terminée, nous racontons notre code comment réagir lorsqu'un événement se termine (comme notre appel AJAX, ou dans ce cas, le délai d'attente).D'utilisation serait:
Qui doivent alerter "5" à l'écran. (Fiddle).
Solutions possibles
Il y a fondamentalement deux manières de procéder pour résoudre ce problème:
1. Synchrone AJAX - ne pas le faire!!
Comme pour AJAX synchrone, ne pas le faire! Felix réponse soulève quelques arguments sur pourquoi c'est une mauvaise idée. Pour résumer, il va geler le navigateur de l'utilisateur jusqu'à ce que le serveur renvoie la réponse et de créer une très mauvaise expérience utilisateur. Voici un bref résumé des prises de MDN sur les raisons:
Si vous ont de le faire, vous pouvez passer d'un drapeau: Voici comment:
2. Restructurer le code
Laissez votre fonction qui accepte un rappel. Dans l'exemple de code
foo
peut être fait pour accepter un rappel. Nous allons dire à nos code comment réagir quandfoo
complète.Donc:
Devient:
Ici, nous sommes passés d'une fonction anonyme, mais on peut tout aussi facilement passer d'une référence à une fonction existante, pour la faire ressembler:
Pour plus de détails sur la façon dont ce genre de rappel de la conception est fait, vérifiez Felix réponse.
Maintenant, nous allons définir foo lui-même à agir en conséquence
(fiddle)
Nous avons maintenant fait notre fonction foo accepter une action à exécuter lorsque l'AJAX se termine avec succès, nous pouvons étendre encore plus loin en vérifiant si l'état de la réponse n'est pas 200 et agir en conséquence (créer un gestionnaire d'échouer et tel). Effectivement la résolution de notre problème.
Si vous rencontrez un moment difficile la compréhension de ce lire l'AJAX guide de mise en route au MDN.
J'ai ajouté une prime sur cette question, je vais voir ce que je peux poisson. Je suis en retrait de la citation de la réponse dans le temps de le dire.
Juste pour la référence, XHR 2 nous permet d'utiliser la
onload
gestionnaire, qui se déclenche uniquement lorsquereadyState
est4
. Bien sûr, il n'est pas pris en charge dans IE8. (iirc, peut-être besoin de confirmation.)Votre explication de la façon de passer d'une fonction anonyme comme un rappel est valide, mais trompeuse. L'exemple var bar = foo(); demande d'une variable à être définis, alors que votre suggestion de foo(functim() {}); ne pas définir bar
Bon les enseignants font dur sujets plus faciles à apprendre. Mauvais enseignants vous faire sentir stupide pour ne pas facilement à l'apprentissage d'une dur de sujet. Merci @BenjaminGruenbaum, Vous avez été un bon professeur ici.
OriginalL'auteur Benjamin Gruenbaum
XMLHttpRequest 2 (tout d'abord lire les réponses de Benjamin Gruenbaum & Felix Kling)
Si vous n'avez pas utiliser jQuery et que vous voulez une belle court XMLHttpRequest 2 qui fonctionne sur les navigateurs modernes et également sur les navigateurs mobiles, je suggère de l'utiliser de cette façon:
Comme vous pouvez le voir:
Il y a deux façons d'obtenir la réponse à l'appel Ajax (trois à l'aide de XMLHttpRequest var nom):
Le plus simple:
Ou si pour quelque raison vous
bind()
le rappel à une classe:Exemple:
Ou (ci-dessus, on est mieux les fonctions anonymes sont toujours un problème):
Rien de plus facile.
Maintenant, certaines personnes diront probablement que c'est mieux d'utiliser onreadystatechange ou le même le XMLHttpRequest nom de la variable. C'est faux.
Découvrez XMLHttpRequest fonctionnalités avancées
Il pris en charge tous les navigateurs modernes. Et je peux confirmer que je suis en utilisant cette approche, car XMLHttpRequest 2 existe. Je n'ai jamais eu n'importe quel type de problème sur tous les navigateurs que j'utilise.
onreadystatechange n'est utile que si vous voulez obtenir les en-têtes de l'état 2.
À l'aide de la
XMLHttpRequest
nom de la variable est une autre grosse erreur que vous avez besoin pour exécuter la fonction de rappel à l'intérieur de la onload/oreadystatechange fermetures d'autre vous l'avez perdu.Maintenant, si vous voulez quelque chose de plus complexe à l'aide de la poste et FormData vous pouvez facilement étendre cette fonction:
De nouveau ... c'est très court, mais c'est & post.
Exemples d'utilisation:
Ou de passer un plein d'élément de formulaire (
document.getElementsByTagName('form')[0]
):Ou de définir certaines valeurs personnalisées:
Comme vous pouvez le voir je n'ai pas l'implémenter la synchronisation... c'est une mauvaise chose.
Cela dit ... pourquoi ne pas le faire facilement?
Comme mentionné dans le commentaire de l'utilisation de l'erreur && synchrone n'briser complètement le point de la réponse. Ce qui est une belle petite façon d'utiliser Ajax dans la bonne façon?
Gestionnaire d'erreur
Dans le script ci-dessus, vous avez un gestionnaire d'erreur, qui est définis de manière statique afin de ne pas compromettre la fonction. Le gestionnaire d'erreur peuvent être utilisés pour d'autres fonctions.
Mais pour avoir vraiment une erreur de la seulement façon est d'écrire une URL erronée dans ce cas, tous les navigateur renvoie une erreur.
Gestionnaires d'erreurs sont peut-être utile si vous définissez des en-têtes personnalisés, définir la responseType blob tableau tampon ou quoi que...
Même si vous passez 'POSTAPAPAP' il ne va pas faire une erreur.
Même si vous passez 'fdggdgilfdghfldj" comme formdata il ne va pas faire une erreur.
Dans le premier cas, l'erreur est à l'intérieur de la
displayAjax()
sousthis.statusText
commeMethod not Allowed
.Dans le second cas, il fonctionne tout simplement. Vous devez vérifier sur le côté serveur si vous avez passé le poteau droit des données.
de la croix-domaine non autorisé déclenche une erreur automatiquement.
Dans la réponse d'erreur, il n'existe pas de codes d'erreur.
Il n'est que le
this.type
qui est définie à l'erreur.Pourquoi ajouter un gestionnaire d'erreur si vous n'avez aucun contrôle sur les erreurs?
La plupart des erreurs sont retournées à l'intérieur de ce dans la fonction de callback
displayAjax()
.Donc: Pas besoin de contrôles d'erreur si vous êtes en mesure de copier et coller l'URL correctement. 😉
PS: Comme le premier test que j'ai écrit x ("x", displayAjax)..., et il a totalement eu une réponse...??? Donc j'ai vérifié le dossier où le HTML est situé, et il y a un fichier appelé 'x.xml'. Donc, même si vous oubliez l'extension de votre fichier XMLHttpRequest 2 TROUVEREZ. I LOL'd
Lire un fichier synchrone
Ne pas le faire.
Si vous souhaitez bloquer le navigateur pour un temps de charge d'une belle grosse
.txt
fichier synchrone.Maintenant vous pouvez le faire
Il n'y a pas d'autre moyen de le faire dans un non-asynchrone. (Ouais, avec setTimeout boucle... mais sérieusement?)
Un autre point, c'est... si vous travaillez avec des Api ou tout simplement votre propre liste de fichiers ou ce que vous utilisez toujours des fonctions différentes pour chaque demande...
Seulement si vous avez une page où vous chargez toujours le même XML/JSON ou tout ce que vous besoin d'une seule fonction. Dans ce cas, de modifier un peu la fonction Ajax et remplacer b avec votre fonction spéciale.
Les fonctions ci-dessus sont pour une utilisation de base.
Si vous souhaitez ÉTENDRE la fonction...
Oui, vous le pouvez.
Je suis avec beaucoup d'Api et de l'une des premières fonctions que j'intégrer dans chaque page HTML est la première Ajax fonction de cette réponse, avec seulement...
Mais vous pouvez faire beaucoup de choses avec XMLHttpRequest 2:
J'ai fait un gestionnaire de téléchargement (à l'aide de plages sur les deux côtés avec un résumé, filereader, système de fichiers), divers image resizers convertisseurs à l'aide de toile, remplir de web des bases de données SQL avec base64images et beaucoup plus... Mais dans ces cas, vous devez créer une fonction uniquement dans ce but... parfois, vous avez besoin d'un blob, tableau des tampons, vous pouvez définir des en-têtes, de remplacer le type mime et il y a beaucoup plus...
Mais la question ici est de savoir comment retourner une réponse Ajax... (j'ai ajouté un moyen facile.)
x
,ajax
ouxhr
pourrait être plus agréable :)). Je ne vois pas comment il aborde le retour de la réponse d'un appel AJAX. (quelqu'un pourrait encore fairevar res = x("url")
et à ne pas comprendre pourquoi ça ne marche pas ;)). Sur une note de côté -, ce serait cool si vous retournéc
de la méthode afin que les utilisateurs puissent crochet surerror
etc.2.ajax is meant to be async.. so NO var res=x('url')..
C'est le but de cette question et réponses 🙂pourquoi est-il un 'c' paramètre dans les fonctions, si sur la première ligne vous êtes écraser quelle que soit la valeur qu'il avait? ai-je raté quelque chose?
Vous pouvez utiliser des paramètres comme un espace réservé pour éviter d'écrire plusieurs fois la "var"
Donc vous avez écrit trompeuse, illisible code dans un réponse pour enregistrer quelques séquences de touches? Merci de ne pas le faire.
OriginalL'auteur cocco
Vous êtes à l'aide d'Ajax de manière incorrecte. L'idée est de ne pas avoir de retour de quoi que ce soit, mais plutôt à la main à partir de ces données de quelque chose qui s'appelle une fonction de rappel, qui gère les données.
Qui est:
De retourner quoi que ce soit dans le gestionnaire de soumission ne sera pas faire quelque chose. Vous devez à la place, soit à la main à partir de ces données, ou de faire ce que vous voulez avec elle directement à l'intérieur de la réussite de la fonction.
success: handleData
et cela fonctionne.Et si vous voulez retourner à la "responseData" en dehors de "handleData" ... 🙂 ... comment allez-vous faire ... ? ... cause d'un simple return pour revenir à la "réussite" de rappel de l'ajax ... et pas à l'extérieur "handleData" ...
hristov Vous avez raté ce point. Gestionnaire de soumission n'est pas la
success
méthode, c'est l'entourant portée de$.ajax
.Je n'ai pas manqué. Si vous avez pris le contenu de handleData et le mettre dans le succès de la méthode il aurait exactement la même chose...
OriginalL'auteur Nic
La solution la plus simple est de créer une fonction JavaScript et de l'appeler pour l'Ajax
success
de rappel.Désolé, j'ai oublié de laisser un commentaire (j'ai l'habitude de le faire!). Je downvoted. Downvotes ne pas indiquer factuelle de l'exactitude ou de l'absence d', ils indiquent l'utilité dans le contexte ou l'absence de. Je ne trouve pas votre réponse utile étant donné Felix qui explique que dans beaucoup plus de détails. Sur une note de côté, pourquoi voudriez-vous stringify la réponse, si c'est du JSON?
ok.. @Benjamin, j'ai utilisé stringify, pour convertir un Objet JSON à la chaîne. Et merci pour clarifier les votre point de vue. Gardera à l'esprit de poster plus d'élaborer des réponses.
Et si vous voulez retourner à la "responseObj" en dehors de "successCallback" ... 🙂 ... comment allez-vous faire ... ? ... cause d'un simple return pour revenir à la "réussite" de rappel de l'ajax ... et pas à l'extérieur "successCallback" ...
OriginalL'auteur Hemant Bavle
Je vais répondre avec un horribles, dessinés à la main de bande dessinée. La deuxième image est la raison pour laquelle
result
estundefined
dans votre exemple de code.Ce serait génial si vous avez ajouté des lignes de code dans chaque image pour illustrer les concepts.
OriginalL'auteur Johannes Fahrenkrug
Angular1
Pour les personnes qui sont à l'aide de AngularJS, de gérer cette situation à l'aide de
Promises
.Ici il dit,
Vous trouverez une belle explication ici aussi.
Exemple trouvé dans docs mentionnés ci-dessous.
Angular2 et plus Tard
Dans
Angular2
avec un coup d'oeil à l'exemple suivant, mais son recommandé à utiliserObservables
avecAngular2
.}
Vous pouvez consommer que de cette manière,
Voir le d'origine poster ici. Mais la Machine ne prend pas en charge natif es6 Promesses, si vous voulez l'utiliser, vous pourriez avoir besoin de plugin pour ça.
En outre, voici les promesses spec définir ici.
Il ne fonctionne pas. promiseB sera 'undefined'
jQuery et fetch les deux méthodes de retour promesses. Je suggère la révision de votre réponse. Si jQuery n'est pas tout à fait le même (puis est là, mais le catch n'est pas).
OriginalL'auteur Maleen Abewardana
Ont un coup d'oeil à cet exemple:
Comme vous pouvez le voir
getJoke
est retour d'un résolu promesse (il est résolu lors du retour deres.data.value
). Alors, vous attendez jusqu'à ce que le $http.obtenir demande est terminée, puis de la console.log(res.blague) est exécutée (normal asynchrone flux).C'est le plnkr:
http://embed.plnkr.co/XlNR7HpCaIhJxskMJfSg/
ES6 moyen (async - attendent)
OriginalL'auteur Francisco Carmona
Une autre approche de renvoyer une valeur à partir d'une fonction d'asynchrone, est de laisser un objet qui va stocker le résultat de la fonction d'asynchrone.
Ici est un exemple de la même:
Je suis en utilisant le
result
objet pour stocker la valeur au cours de l'opération asynchrone. Cela permet que le résultat soit disponible, même après le travail asynchrone.- Je utiliser cette approche beaucoup. Je serais intéressé de savoir comment cette approche fonctionne à où le câblage le résultat de retour par le biais de modules consécutifs est impliqué.
result
. Cela fonctionne parce que vous êtes la lecture de la variable après de la fonction async est terminée.OriginalL'auteur jsbisht
C'est l'un des lieux qui deux façons de liaison de données qui est utilisé dans de nombreux nouveaux frameworks JavaScript sera parfait pour vous...
Donc, si vous utilisez Angulaire, de Réagir ou tout autres cadres qui ne deux façons de liaison de données ou concept de magasin cette question est tout simplement fixe, de sorte facile word, votre résultat est
undefined
lors de la première étape, si vous avez euresult = undefined
avant de recevoir les données, puis dès que vous obtenez le résultat, il sera mis à jour et assignés à la nouvelle valeur de réponse de votre appel Ajax...Mais comment vous pouvez le faire dans le plus pur javascript ou jQuery par exemple, comme vous l'avez demandé dans cette question?
Vous pouvez utiliser un rappel, promesse et récemment observables pour gérer cela pour vous, par exemple, dans les promesses que nous avons certaines fonctions comme la réussite() ou() qui sera exécutée lors de vos données est prête pour vous-même avec rappel ou abonnez-vous fonction observables.
Par exemple dans votre cas, qui que vous utilisez jQuery, vous pouvez faire quelque chose comme ceci:
Pour plus d'informations, étude sur promesses et observables qui sont de nouvelles façons de faire ce async animaux.
$.ajax({url: "api/data", success: fooDone.bind(this)});
C'est en fait incorrect que de Réagir est un moyen de liaison de données
vous n'êtes pas mauvais, mais pas aussi, de Réagir accessoires d'objet et si changé, qu'ils changent tout au long de l'application, mais ce n'est pas une façon de Réagir développeur recommandent de l'utiliser...
OriginalL'auteur Alireza
Tandis que les promesses et les rappels fonctionnent très bien dans de nombreuses situations, il est une douleur à l'arrière d'exprimer quelque chose comme:
Vous finirais en passant par
async1
; vérifier siname
est pas défini ou non, et appeler la fonction de rappel en conséquence.Alors qu'il est bon dans de petits exemples, c'est embêtant quand vous avez beaucoup de cas similaires et d'erreur de manipulation en cause.
Fibers
aide dans la résolution de la question.Vous pouvez télécharger le projet ici.
est-il semblable générateur de fonctions? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...*
Est-ce toujours d'actualité?
Vous pouvez faire usage de
async-await
si vous êtes en utilisant certaines des versions les plus récentes de nœud. Si quelqu'un est coincé avec les anciennes versions, ils peuvent utiliser cette méthode.OriginalL'auteur rohithpr
Réponse courte est, vous avez à mettre en œuvre un rappel comme ceci:
OriginalL'auteur Pablo Matias Gomez
2017 réponse: vous pouvez maintenant faire exactement ce que vous voulez dans chaque navigateur actuel et le nœud
C'est assez simple:
Voici une version de travail de votre code:
attendent est pris en charge dans tous les navigateurs actuels et le nœud 8
le nœud 8 inclut nodejs.org/api/util.html#util_util_promisify_original, qui peut être utilisé pour faire de l'node.js API de revenir promesses. Si vous avez le temps et l'argent pour soutenir des navigateurs actuels dépend évidemment de votre situation.
IE 11 est encore un navigateur actuel en 2018, malheureusement, et il ne prend pas en charge
await/async
IE11 est pas un navigateur récent. Il a été publié il y a 5 ans, a une part de marché mondiale de 2,5% selon caniuse, et à moins que quelqu'un est en doublant votre budget d'ignorer toute la technologie actuelle, alors il ne vaut pas la plupart du temps aux gens.
OriginalL'auteur mikemaccana
Vous pouvez utiliser cette bibliothèque personnalisée (écrite à l'aide de la Promesse) pour effectuer un appel à distance.
Simple exemple d'utilisation:
OriginalL'auteur Vinoth Rajendran
Navigateur peut être divisé en trois parties:
1)Boucle D'Événement De
2)de l'API Web
3)File D'Attente D'Événements
Boucle d'événement de pistes pour toujours je.e sorte de boucle infinie.File d'attente d'événements est l'endroit où tous vos fonction sont poussés sur un événement(exemple:cliquez sur) c'est un par un procédé de file d'attente et le mettre dans la boucle d'Événements dont l'exécution de cette fonction et le prépare soi-même pour ensuite l'un après premier est exécuté.Cela signifie que l'Exécution d'une fonction, de ne pas démarre jusqu'à la fonction avant de la file d'attente est exécutée en boucle d'événements.
Maintenant, laissez-nous penser, nous avons poussé les deux fonctions dans une file d'attente est pour obtenir des données à partir du serveur et l'autre utilise des données.Nous avons poussé la serverRequest() fonction dans la file d'attente d'abord, puis utiliseData() fonction. serverRequest fonction passe dans la boucle d'événement et fait un appel au serveur que nous ne savons jamais combien de temps il faudra pour obtenir les données à partir du serveur
donc, ce processus devrait prendre du temps et donc nous avons occupé notre boucle d'événement ainsi la pendaison de notre page, c'est là que l'API Web de venir dans le rôle profiter de cette fonction de boucle d'événements et de transactions avec le serveur événement de boucle, de sorte que nous pouvons exécuter la fonction suivante de la file d'attente.La fonction suivante dans la file d'attente est utiliseData() qui passe en boucle, mais en raison de l'absence de données disponibles, il va de déchets et de l'exécution de la prochaine fonction continue jusqu'à la fin de la file d'attente.(Ce qui est appelé Async appel je.e nous pouvons faire autre chose jusqu'à ce que nous obtenir des données)
Supposons notre serverRequest() la fonction a une instruction de retour dans un code, lorsque nous revenons de données à partir du serveur Web API va le pousser dans la file d'attente à la fin de la file d'attente.
Comme il obtenir poussé à la fin de la file d'attente on ne peut pas utiliser ses données comme il n'existe pas de fonction de gauche dans notre file d'attente à utiliser ces données.Ainsi, il n'est pas possible de retourner quelque chose d'Appel Asynchrone.
Donc la Solution c'est rappel ou promesse.
Une Image de l'une des réponses ici, Correctement explique rappel de l'utilisation...
Nous donnons notre fonction(fonction en utilisant les données renvoyées par le serveur) à la fonction d'appel serveur.
Dans mon Code, il est appelé comme
Lire ici pour les nouvelles méthodes de l'ECMA(2016/17) pour faire appel asynchrone(@Felix Kling Réponse sur le Dessus)
https://stackoverflow.com/a/14220323/7579856
OriginalL'auteur Aniket Jha
C'est un problème très commun nous sommes confrontés tout en luttant contre les "mystères" de JavaScript. Laissez-moi essayer de démystifier ce mystère aujourd'hui.
Commençons par une simple fonction JavaScript:
C'est un simple appel de fonction synchrone (où chaque ligne de code est "terminé avec son travail" avant que le suivant dans la séquence), et le résultat est le même que prévu.
Maintenant, nous allons ajouter un peu de torsion, en introduisant peu de retard dans notre fonction, de sorte que toutes les lignes de code ne sont pas "fini" dans la séquence. Ainsi, il va émuler le comportement asynchrone de la fonction :
Donc là vous allez, que le retard vient de se casser la fonctionnalité que nous attendions! Mais qu'est-ce qui s'est passé ? Eh bien, c'est en fait assez logique si vous regardez le code. la fonction
foo()
, lors de son exécution, ne retourne rien (donc la valeur de retour estundefined
), mais il n'démarrer une minuterie, qui exécute une fonction après 1s retourner "wohoo'. Mais comme vous pouvez le voir, la valeur attribuée à bar est immédiatement retourné trucs de foo(), pas autre chose qui vient plus tard.Alors, comment pouvons-nous résoudre ce problème?
Demandons à notre fonction pour un PROMESSE.
La promesse est vraiment sur ce que cela signifie : il signifie que la fonction vous garantit de fournir avec toute sortie il obtient dans l'avenir. donc, nous allons le voir en action pour notre petit problème ci-dessus :
Ainsi, le résumé est - à lutter contre l'asynchrone, comme les fonctions ajax basé sur des appels etc., vous pouvez utiliser une promesse de
resolve
la valeur (qui vous l'intention de revenir). Donc, en bref, vous résoudre valeur au lieu de retour, en asynchrone fonctions.Mise à JOUR (Promesses avec async/await)
En dehors de l'aide
then/catch
de travailler avec des promesses, il y en a plus. L'idée est de reconnaître une fonction d'asynchrone et puis attendre les promesses à résoudre, avant de passer à la ligne suivante de code. Il est encore juste lepromises
sous le capot, mais avec une autre approche syntaxique. Pour rendre les choses plus claires, vous pouvez trouver un comparatif ci-dessous:alors/catch version:
async/await version:
Personnellement, je ne pense pas que la meilleure façon en tant que tel. J'utilise des promesses puis/catch , async/await ainsi que des générateurs pour async des parties de mon code. Elle dépend en grande partie sur le contexte d'utilisation.
OriginalL'auteur Anish K.
ECMAScript 6 a 'des générateurs", qui vous permettent de programmer facilement en asynchrone style.
Pour exécuter le code ci-dessus pour ce faire:
Si vous avez besoin de cibler les navigateurs qui ne supportent pas l'ES6, vous pouvez exécuter le code par le biais de Babel ou la fermeture-compilateur pour générer ECMAScript 5.
Le rappel
...args
sont enveloppés dans un tableau et déstructuré, lorsque vous les lisez, de sorte que le motif peut faire face à des rappels qui ont plusieurs arguments. Par exemple avec nœud fs:OriginalL'auteur James
Réponse courte: Votre
foo()
méthode retourne immédiatement, tandis que la$ajax()
appel s'exécute de façon asynchrone après la fonction renvoie. Le problème est alors de savoir comment et où stocker les résultats récupérés par l'appel asynchrone une fois qu'il retourne.Plusieurs solutions ont été donné dans ce fil. Peut-être la façon la plus simple est de passer d'un objet à la
foo()
méthode, et de stocker les résultats dans un membre de l'objet après l'appel asynchrone est terminée.Noter que l'appel à
foo()
retournera toujours rien d'utile. Cependant, le résultat de l'appel asynchrone seront désormais stockées dansresult.response
.OriginalL'auteur David R Tribble
Utiliser un
callback()
fonction à l'intérieur de lafoo()
succès.Essayez de cette façon. Il est simple et facile à comprendre.
OriginalL'auteur Mahfuzur Rahman
Nous nous trouvons dans un univers qui semble progresser le long d'une dimension que nous appelons "temps". Nous ne comprenons pas vraiment quelle heure il est, mais nous avons développé des abstractions et de vocabulaire qui nous permettent de raison et d'en parler: "passé", "présent", "futur", "avant", "après".
Les systèmes informatiques de nous construire, de plus en plus-être le temps est une dimension importante. Certaines choses sont mises en place pour arriver dans le futur. Puis d'autres choses qui doivent arriver après celles des premières choses éventuellement se produire. C'est l'idée de base appelé "l'asynchronicité". De plus en plus dans notre monde en réseau, le cas le plus fréquent de l'asynchronicité est en attente pour certains à distance de système à répondre à une demande.
Prenons un exemple. Vous appelez le berger et l'ordre du lait. Quand il s'agit, vous voulez mettre dans votre café. Vous ne pouvez pas mettre le lait dans votre café maintenant, parce qu'il n'est pas encore là. Vous devez attendre qu'il vienne avant de le mettre dans votre café. En d'autres mots, le code suivant ne fonctionne pas:
Parce que JS n'a aucun moyen de savoir qu'il doit attendre pour
order_milk
à terminer avant d'exécuterput_in_coffee
. En d'autres termes, il ne sait pas queorder_milk
est asynchrone - est quelque chose qui n'est pas le résultat de lait jusqu'à un certain moment dans l'avenir. JS, et d'autres langages déclaratifs de l'exécution d'une instruction après l'autre sans attendre.Le classique JS approche à ce problème, en tirant parti du fait que JS prend en charge les fonctions comme des objets de première classe qui peut être passé autour de, est de passer une fonction en tant que paramètre à la requête asynchrone, qui sera ensuite invoquer quand il a terminé sa tâche dans l'avenir. C'est le "rappel" de la démarche. Il ressemble à ceci:
order_milk
coup d'envoi, les commandes le lait, puis, quand et seulement quand il arrive, il invoqueput_in_coffee
.Le problème avec ce rappel à l'approche, c'est qu'il pollue la sémantique normale d'une fonction de reporting son résultat avec
return
; au lieu de cela, les fonctions doivent pas les rapports de leurs résultats en appelant à un rappel donné comme paramètre. Aussi, cette approche peut rapidement devenir difficile à gérer lorsque l'on traite avec de plus longues séquences d'événements. Par exemple, disons que je veux attendre le lait à mettre dans le café, et ensuite, et seulement ensuite effectuer une troisième étape, à savoir boire le café. Je finis par avoir besoin d'écrire quelque chose comme ceci:où je suis de passage à
put_in_coffee
à la fois le lait à mettre dedans, et de l'action (drink_coffee
) à exécuter une fois que le lait a été mis en place. Ce code devient difficile d'écrire, et lire, et de débogage.Dans ce cas, on pourrait réécrire le code en question:
Entrer promesses
C'était la motivation de la notion de "promesse", qui est un type particulier de valeur qui représente un avenir ou asynchrone résultat d'une certaine sorte. Il peut représenter quelque chose qui est déjà arrivé, ou qui va arriver dans le futur, ou ne pourrait jamais arriver à tous. Les promesses n'ont pas une seule méthode, nommée
then
, pour lequel vous passez une action à exécuter lorsque le résultat de la promesse a été réalisé.Dans le cas de notre lait et de café, nous concevons
order_milk
pour retourner une promesse pour le lait en arrivant, puis spécifiezput_in_coffee
comme unthen
action, comme suit:Un avantage de cela est que nous pouvons chaîne de créer des séquences d'événements futurs ("chaîne"):
Nous allons appliquer les promesses de votre problème particulier. Nous terminerons notre demande, la logique à l'intérieur d'une fonction, qui renvoie une promesse:
En fait, tout ce que nous avons fait est ajouté un
return
à l'appel à$.ajax
. Cela fonctionne parce que jQuery$.ajax
retourne déjà une sorte de promesse. (Dans la pratique, sans entrer dans les détails, nous préférons pour l'envelopper de cet appel ainsi que pour le retour d'une vraie promesse, ou d'utiliser une alternative à$.ajax
qui le font.) Maintenant, si on veut charger le fichier et attendre qu'elle se termine et puis faire quelque chose, nous pouvons simplement direpar exemple,
Lors de l'utilisation de promesses, nous finissons par passer beaucoup de fonctions dans
then
, de sorte qu'il est souvent utile d'utiliser le plus compact ES6-flèche de style de fonctions:La
async
mot-cléMais il y a toujours quelque chose de vaguement insatisfaisante sur le fait d'avoir à écrire le code d'une façon si synchrone et d'une tout autre façon, si asynchrone. Synchrone, nous écrire
mais si
a
est asynchrone, avec des promesses que nous avons à écrireCi-dessus, nous l'avons dit, "JS n'a aucun moyen de savoir qu'il doit attendre pour le premier appel avant la fin de l'exécution de la deuxième". Ne serait-il pas agréable si il y était d'une certaine façon de dire JS? Il s'avère qu'il y a--la
await
mot-clé, à l'intérieur d'un type spécial de la fonction appelée un "async" de la fonction. Cette fonctionnalité fait partie de la prochaine version de ES, mais est déjà disponible en transpilers tels que Babel donné le droit de presets. Cela nous permet d'écrire tout simplementDans votre cas, vous pouvez écrire quelque chose comme
OriginalL'auteur
Bien sûr, il existe de nombreuses approches comme synchrone demande, de la promesse, mais de mon expérience, je pense que vous devriez utiliser la fonction de rappel de l'approche. Il est naturel de comportement asynchrone de Javascript.
Donc, votre extrait de code peut être réécrire un peu différent:
OriginalL'auteur Khoa Bui
La question était:
qui PEUT être interprété comme:
La solution sera d'éviter les rappels, et utiliser une combinaison de Promesses et async/await.
Je voudrais donner un exemple d'une requête Ajax.
(Bien qu'il puisse être écrit en Javascript, je préfère l'écrire en Python, et le compiler en Javascript à l'aide de Transcrypt. Il sera assez clair.)
Permet d'abord de permettre l'utilisation de JQuery, pour avoir
$
disponible enS
:Définir une fonction qui retourne un Promesse, dans ce cas, un appel Ajax:
Utiliser le asynchrone code comme si c'était synchrone:
OriginalL'auteur Pieter Jan Bonestroo
Voyons d'abord la forêt avant de regarder les arbres.
Il y a beaucoup d'instructif réponses avec beaucoup de détails ici, je ne vais pas répéter l'un d'eux. La clé de la programmation en JavaScript est d'avoir d'abord le corriger modèle mental de l'ensemble de l'exécution.
exemple, une balise de script avec le code est chargé dans le navigateur.
(En conséquence, c'est pourquoi vous devrez peut-être concerné par l'
préparation de la page pour l'exécution de votre code, si elle exige des éléments du dom
pour être construit en premier, etc.)
fait-sans que l'exécution de tout de vos rappels, y compris XHR
les demandes, définir les délais, dom gestionnaires d'événements, etc. Chacun de ces rappels en attente d'être exécutés va s'asseoir dans une file d'attente, attendant leur tour pour être exécuté après d'autres événements que les licenciés ont fini de l'exécution.
l'événement une fois invoquée sera alors exécuté jusqu'à la fin.
La bonne nouvelle est que si vous comprenez bien, vous n'aurez jamais à vous soucier des conditions de course. Vous devez d'abord et avant tout chose de la façon dont vous souhaitez organiser votre code essentiellement comme la réponse à différents événements discrets, et comment vous voulez le thread dans un ordre logique. Vous pouvez utiliser des promesses ou de niveau plus élevé de nouveaux async/await comme des outils à cette fin, ou vous pouvez rouler votre propre.
Mais vous ne devriez pas utiliser toute la tactique des outils pour résoudre un problème jusqu'à ce que vous êtes à l'aise avec le problème réel de domaine. Dessiner une carte de ces dépendances pour savoir ce qui doit s'exécuter lorsque. Tenter une approche ad-hoc pour tous ces rappels est tout simplement pas aller bien vous servir.
OriginalL'auteur Haim Zamir
À l'aide de ES2017 vous devriez avoir ce que la déclaration de la fonction
Et l'exécution de ce genre.
Ou la Promesse de syntaxe
OriginalL'auteur Fernando Carvajal
Plutôt que de jeter de code à vous, il y a 2 concepts que sont la clé pour comprendre comment JS poignées de rappels et de l'asynchronicité. (est-ce encore un mot?)
La Boucle d'Événement et de Simultanéité Modèle
Il y a trois choses que vous devez être conscient de; La file d'attente; la boucle d'événements et la pile
En large, en termes simplistes, la boucle d'événements, c'est comme le gestionnaire de projet, il est constamment à l'écoute de toutes les fonctions que voulez exécuter et communique entre la file d'attente et la pile.
Une fois qu'il reçoit un message d'exécuter quelque chose, il l'ajoute à la file d'attente. La file d'attente est la liste des choses qui sont en attente d'exécution (comme votre requête AJAX). imagine comme ça:
Lorsque l'un de ces messages s'apprête à exécuter, il apparaît le message de la file d'attente et crée une pile, la pile est tout le JS doit exécuter pour exécuter l'instruction dans le message. Ainsi, dans notre exemple, il est dit d'appeler
foobarFunc
Donc tout ce qui foobarFunc a besoin pour s'exécuter (dans notre cas
anotherFunction
) obtenir poussé sur la pile. exécutée, et puis oublié - la boucle d'événement va alors se déplacer sur la chose suivante dans la file d'attente (ou écouter les messages)Le point clé ici est de l'ordre de l'exécution. C'est
QUAND quelque chose va courir
Lorsque vous effectuez un appel à l'aide d'AJAX à un tiers ou à exécuter n'importe quel code asynchrone (un setTimeout par exemple), le Javascript est tributaire d'une réponse avant de procéder.
La grande question est: quand est-il d'obtenir la réponse? La réponse est que nous ne savons pas - de sorte que la boucle d'événement est en attente de ce message pour dire "hey run-moi". Si JS juste attendu pour ce message de façon synchrone votre application aurait pour effet de geler et il va le sucer. Donc, JS porte sur l'exécution de l'élément suivant dans la file d'attente en attendant que le message à faire de nouveau ajouté à la file d'attente.
C'est pourquoi avec asynchrone fonctionnalité nous utilisons des choses que l'on appelle rappels. C'est un peu comme un promesse littéralement. Comme je promesse de retourner quelque chose à un certain point jQuery utilise spécifiques rappels appelé
deffered.done
deffered.fail
etdeffered.always
(parmi d'autres). Vous pouvez les voir tous les iciDonc ce que vous devez faire est de passer une fonction qui est promis de les exécuter à un certain point avec les données qui lui est passé.
Parce qu'un rappel n'est pas exécutée immédiatement, mais plus tard il est important de passer la référence à la fonction n'est pas exécuté. donc
donc la plupart du temps (mais pas toujours), vous allez passer
foo
pasfoo()
J'espère que ça va faire un certain sens. Lorsque vous rencontrez ce genre de choses qui semblent confus je recommande fortement la lecture de la documentation entièrement d'obtenir au moins une compréhension de celui-ci. Il va vous faire un bien meilleur développeur.
OriginalL'auteur Matthew Brent