2014-06-11 15 views
31

Ich habe es mit einem NodeJs-Framework zu tun, das eine bestimmte Funktion benötigt, um synchron zu sein, aber ich muss einen Wert abrufen, auf den nur asynchron zugegriffen werden kann. In einer perfekten Welt könnte ich ein Versprechen geben, aber ich kann nicht.Wie warte ich darauf, dass ein Versprechen gelöst wird?

Als schnelle und unsaubere Lösung, habe ich die folgende Methode:

exports.synchronizePromise = function(promise) { 
    var value; 
    promise.then(function(promiseValue) { 
     value = promiseValue; 
    }); 
    while (!value) {} // Wait for promise to resolve 
    console.log("DONE: " + value); // Never reached 
    return value; 
}; 

Aber ich erhalte eine Fehlermeldung. Gibt es einen Weg, um das zu erreichen, was ich brauche?

+4

Versprechungen machen die Dinge nicht magisch, sie machen nur einige asynchrone Prozesse einfacher zu codieren und durch mehrere Schritte zu verwalten. Verwenden Sie keine Schleife, um einzufrieren, sondern beheben Sie das Problem im Upstream, indem Sie die Synchronisation in zwei Teile aufteilen. – dandavis

+2

@dandavis Ich überlegte, ein commit für das Framework zu machen, das ich benutze, um es so zu machen, dass die Funktion async sein kann, aber es wird an zu vielen Stellen aufgerufen und in 99% der Fälle muss es nicht asynchron sein. Es ist nicht wirklich eine Option, es stromaufwärts zu reparieren. –

+0

Sie können sofort eine GUID nach dem Senden des Prozesses zurückgeben, und wenn der Prozess abgeschlossen ist, finden Sie die Guid in Ihrem data/dom und ersetzen Sie für den tatsächlichen Wert. – dandavis

Antwort

2

In Q, wenn Sie ein aufgelöstes Versprechen haben, können Sie nur den Wert nehmen mit

inspizieren
exports.synchronizePromise = function(promise) { 
    var i = promise.inspect(); 
    if (i.state === "rejected") { 
     throw i.reason; 
    } else if (i.state === "fulfilled") { 
     return i.value; 
    } else { 
     throw new Error("attempt to synchronize pending promise") 
    } 
}; 

Allerdings, wenn das Versprechen anhängig ist, ist es wirklich asynchron und Ihre Frage dann nicht sinnvoll, und die Funktion wird einen Fehler auslösen.

+0

Danke. Ich habe vergessen, dass NodeJs single threaded ist, also dachte ich, ich könnte einfach warten, bis es gelöst ist. –

+0

@ sinθ Sie können warten, bis es gelöst ist, das ist was. Dann ist, nur diesen Funktionsaufruf in den '.then 'Block. –

+0

Wie hilft die Überprüfung des Wertes des aufgelösten Versprechens hier? –

-1

Versprechen sind asynchron. Sie stellen einen zukünftigen Wert dar - einen Wert, der in 1 ms oder 1 Minute oder 1 Tag oder 1 Jahr in der Zukunft oder nie verfügbar ist. Per Definition gibt es keine Möglichkeit, sie zu "zwingen", anders als eine Zeitmaschine zu lösen.

Wenn Sie eine vorgelagerte Logik haben, die auf der Voraussetzung der Synchronität aufgebaut ist, aber aus welchen Gründen auch immer sie nun asynchron ist, müssen Sie diese vorgelagerte Komponente umgestalten, um asynchron zu arbeiten. Es gibt keine andere Alternative.

Wenn Ihr Framework "eine bestimmte Funktion benötigt, um synchron zu sein", wenn diese Funktion nicht synchron ist oder nicht synchron sein kann, ist das Framework schlecht entworfen und unbrauchbar oder zumindest nicht für Ihr Problem verwendbar.

+13

Während ein gültiger Punkt, ist es tangential zu der eigentlichen Frage, die über das Lösen von Versprechen ist. Auflösungsversprechen haben einen Wert, der über diesen speziellen Anwendungsfall hinausgeht. – Siddhu

+0

@siddhuwarrier Nicht ganz sicher, was Sie zu sagen versuchen. Grundsätzlich können Sie ein Versprechen nicht lösen; Das Versprechen löst sich selbst (oder nicht) und alles, was Sie tun können, ist darauf zu warten, dass dies geschieht. Oder fehlt mir etwas? Was meinst du mit "Versprechen lösen"? –

+0

Worauf ich hingewiesen habe, war ein Mechanismus, mit dem Sie auf das Ergebnis eines asynchronen Vorgangs warten können. Zum Beispiel in Scala, ' val f = Future {...}; f.map { item => // Aktion mit zukünftigem Ergebnis ausführen } .recover { // Handle-Fehler }; erwartet.Ergebnis (f, 10000 Millisekunden); ' Ein Anwendungsfall für etwas wie dieses ist, dass die Zukunft selbst mehrere Threads parallel ausführen könnte, um ein Ergebnis zu erzeugen, während der Haupt-Thread darauf wartet, dass er beendet wird. – Siddhu

3

Da dieser Knoten standardmäßig nur single threaded ist, gibt es nicht wirklich eine einfache Möglichkeit, dies zu lösen. Es gibt jedoch eins. Basen auf Generatoren/Fasern können Sie eine Art der gleichzeitigen Ausführung zum Knoten hinzufügen. Darauf basiert eine waitfor implementation.

Verwandte Themen