J'ai une fonction simplifiée qui ressemble à ceci:
function(query) {
myApi.exec('SomeCommand', function(response) {
return response;
});
}
Fondamentalement, je veux qu'il appelle myApi.exec
et renvoie la réponse qui est donnée dans le lambda de rappel. Cependant, le code ci-dessus ne fonctionne pas et revient simplement immédiatement.
Juste pour une tentative très hackish, j'ai essayé ce qui n'a pas fonctionné, mais au moins vous avez une idée de ce que j'essaie de réaliser:
function(query) {
var r;
myApi.exec('SomeCommand', function(response) {
r = response;
});
while (!r) {}
return r;
}
Fondamentalement, quelle est la bonne façon de procéder à cet égard? Node.js / event driven? Je veux que ma fonction attende que le rappel soit appelé, puis renvoie la valeur qui lui a été transmise.
Réponses:
La bonne façon de faire ceci: node.js / event driven est de ne pas attendre .
Comme presque tout le reste lorsque vous travaillez avec des systèmes pilotés par des événements comme le nœud, votre fonction doit accepter un paramètre de rappel qui sera invoqué une fois le calcul terminé. L'appelant ne doit pas attendre que la valeur soit "renvoyée" dans le sens normal, mais plutôt envoyer la routine qui gérera la valeur résultante:
Donc, vous ne l'utilisez pas comme ceci:
Mais comme ça:
la source
fs
sync*
méthodes). En tant que tel, je pense que c'est toujours une question valable. Existe-t-il un bon moyen de bloquer le nœud en dehors de l'attente occupée?sync
méthodes. (2) Utilisez des fibres, github.com/laverdet/node-fibers , (3) Utilisez des promesses, par exemple la bibliothèque Q, (4) Utilisez une couche mince au-dessus de javascript, qui semble bloquante, mais se compile en async, comme maxtaco.github.com/coffee-scriptUne façon d'y parvenir consiste à encapsuler l'appel d'API dans une promesse, puis à utiliser
await
pour attendre le résultat.Production:
la source
async/await
Je n'en ai pas souvent besoin, alors ayez du mal à vous souvenir comment gérer cette situation, je le copie pour mes notes / références personnelles.vérifiez ceci: https://github.com/luciotato/waitfor-ES6
votre code avec wait.for: (nécessite des générateurs, drapeau --harmony)
la source
Si vous ne souhaitez pas utiliser le rappel, vous pouvez utiliser le module "Q".
Par exemple:
Pour plus d'informations, référez-vous à ceci: https://github.com/kriskowal/q
la source
Si vous le voulez très simple et facile, pas de bibliothèques fantaisies, attendre que les fonctions de rappel soient exécutées dans le nœud, avant d'exécuter un autre code, c'est comme ceci:
la source
Remarque: Cette réponse ne devrait probablement pas être utilisée dans le code de production. C'est un hack et vous devez en connaître les implications.
Il y a le module uvrun (mis à jour pour les nouvelles versions de Nodejs ici ) où vous pouvez exécuter un seul tour de boucle de la boucle d'événement principal libuv (qui est la boucle principale de Nodejs).
Votre code ressemblerait à ceci:
(Vous pouvez utiliser une alternative
uvrun.runNoWait()
. Cela pourrait éviter certains problèmes de blocage, mais prend 100% de CPU.)Notez que cette approche invalide en quelque sorte le but de Nodejs, c'est-à-dire que tout est asynchrone et non bloquant. En outre, cela pourrait augmenter considérablement la profondeur de votre pile d'appels, vous pourriez donc vous retrouver avec des débordements de pile. Si vous exécutez une telle fonction récursivement, vous rencontrerez certainement des problèmes.
Voir les autres réponses sur la façon de reconcevoir votre code pour le faire "bien".
Cette solution ici n'est probablement utile que lorsque vous effectuez des tests et esp. voulez avoir synchronisé et code série.
la source
Depuis le nœud 4.8.0, vous pouvez utiliser la fonctionnalité d'ES6 appelée générateur. Vous pouvez suivre cet article pour des concepts plus approfondis. Mais en gros, vous pouvez utiliser des générateurs et promets de faire ce travail. J'utilise Bluebird à promisify et gérer le générateur.
Votre code devrait être correct comme dans l'exemple ci-dessous.
la source
en supposant que vous ayez une fonction:
vous pouvez utiliser des rappels comme celui-ci:
la source
Cela va à l'encontre du but des E / S non bloquantes - vous le bloquez quand il n'a pas besoin de le bloquer
:)
Vous devez imbriquer vos rappels au lieu de forcer node.js à attendre, ou appeler un autre rappel à l'intérieur du rappel où vous avez besoin du résultat
r
.Si vous devez forcer le blocage, il y a de fortes chances que vous pensiez mal à votre architecture.
la source
http.get()
une URL etconsole.log()
son contenu. Pourquoi dois-je sauter en arrière pour le faire dans Node?Utiliser async et attendre est beaucoup plus facile.
la source