Ich habe eine vereinfachte Funktion, die so aussieht:
function(query) {
myApi.exec('SomeCommand', function(response) {
return response;
});
}
Grundsätzlich möchte ich, dass es aufruft myApi.exec
und die Antwort zurückgibt, die im Rückruf-Lambda gegeben wird. Der obige Code funktioniert jedoch nicht und kehrt einfach sofort zurück.
Nur für einen sehr hackigen Versuch habe ich das Folgende ausprobiert, was nicht funktioniert hat, aber zumindest kommt Ihnen die Idee, was ich erreichen möchte:
function(query) {
var r;
myApi.exec('SomeCommand', function(response) {
r = response;
});
while (!r) {}
return r;
}
Was ist im Grunde eine gute "node.js / event-gesteuerte" Vorgehensweise? Ich möchte, dass meine Funktion wartet, bis der Rückruf aufgerufen wird, und dann den Wert zurückgibt, der an sie übergeben wurde.
Antworten:
Die "gute node.js / eventgesteuerte" Methode, dies zu tun, besteht darin, nicht zu warten .
Wie fast alles andere bei der Arbeit mit ereignisgesteuerten Systemen wie Node sollte Ihre Funktion einen Rückrufparameter akzeptieren, der aufgerufen wird, wenn die Berechnung abgeschlossen ist. Der Aufrufer sollte nicht warten, bis der Wert im normalen Sinne "zurückgegeben" wird, sondern die Routine senden, die den resultierenden Wert verarbeitet:
Also benutzt du es nicht so:
Aber so:
quelle
fs
sync*
Methoden). Insofern halte ich dies immer noch für eine berechtigte Frage. Gibt es eine gute Möglichkeit, das Blockieren im Knoten zu erreichen, abgesehen vom geschäftigen Warten?sync
Methoden. (2) Verwenden Sie Fasern, github.com/laverdet/node-fibers . (3) Verwenden Sie Versprechen, z. B. die Q-Bibliothek. (4) Verwenden Sie eine dünne Schicht über Javascript, die blockiert aussieht, aber asynchron kompiliert wird. wie maxtaco.github.com/coffee-scriptEine Möglichkeit, dies zu erreichen, besteht darin, den API-Aufruf in ein Versprechen zu verpacken und dann
await
auf das Ergebnis zu warten.Ausgabe:
quelle
async/await
Ich brauche dies nicht oft. Sie haben also Probleme, sich daran zu erinnern, wie Sie mit dieser Situation umgehen sollen. Ich kopiere dies für meine persönlichen Notizen / Referenzen.Überprüfen Sie dies: https://github.com/luciotato/waitfor-ES6
Ihr Code mit wait.for: (erfordert Generatoren, --harmony Flag)
quelle
Wenn Sie den Rückruf nicht verwenden möchten, können Sie das Modul "Q" verwenden.
Beispielsweise:
Weitere Informationen finden Sie unter: https://github.com/kriskowal/q
quelle
Wenn Sie möchten, dass es sehr einfach und unkompliziert ist, warten Sie auf die Ausführung von Rückruffunktionen im Knoten, bevor Sie einen anderen Code ausführen:
quelle
Hinweis: Diese Antwort sollte wahrscheinlich nicht im Produktionscode verwendet werden. Es ist ein Hack und Sie sollten über die Auswirkungen Bescheid wissen.
Es ist das uvrun Modul (aktualisiert für neuere Versionen NodeJS hier ) , wo man eine einzige Schleife Runde der libuv Hauptereignisschleife ausführen kann (die die NodeJS Hauptschleife ist).
Ihr Code würde folgendermaßen aussehen:
(Sie könnten eine alternative Verwendung verwenden
uvrun.runNoWait()
. Dadurch könnten einige Probleme beim Blockieren vermieden werden, es wird jedoch 100% CPU benötigt.)Beachten Sie, dass dieser Ansatz den gesamten Zweck von Nodejs ungültig macht, dh alles asynchron und nicht blockierend zu machen. Außerdem kann dies die Callstack-Tiefe erheblich erhöhen, sodass möglicherweise Stapelüberläufe auftreten. Wenn Sie eine solche Funktion rekursiv ausführen, werden Sie definitiv auf Probleme stoßen.
In den anderen Antworten erfahren Sie, wie Sie Ihren Code neu gestalten, um ihn "richtig" zu machen.
Diese Lösung hier ist wahrscheinlich nur nützlich, wenn Sie testen und esp. möchte synchronisierten und seriellen Code haben.
quelle
Seit Knoten 4.8.0 können Sie die als Generator bezeichnete Funktion von ES6 verwenden. Sie können diesem Artikel für tiefere Konzepte folgen . Aber im Grunde können Sie Generatoren und Versprechen verwenden, um diese Arbeit zu erledigen. Ich benutze Bluebird , um den Generator zu versprechen und zu verwalten.
Ihr Code sollte wie im folgenden Beispiel in Ordnung sein.
quelle
Angenommen, Sie haben eine Funktion:
Sie können Rückrufe wie folgt verwenden:
quelle
Das macht den Zweck des nicht blockierenden E / A zunichte - Sie blockieren es, wenn es nicht blockiert werden muss
:)
Sie sollten Ihre Rückrufe verschachteln, anstatt node.js zum Warten zu zwingen, oder einen anderen Rückruf innerhalb des Rückrufs aufrufen, bei dem Sie das Ergebnis von benötigen
r
.Wenn Sie das Blockieren erzwingen müssen, denken Sie wahrscheinlich an Ihre Architektur.
quelle
http.get()
eine URL undconsole.log()
deren Inhalt schreiben . Warum muss ich rückwärts springen, um das in Node zu tun?Mit Async und Warten ist es viel einfacher.
quelle