Wie kann man auf den Wert eines Versprechens zugreifen?

146

Ich schaue mir dieses Beispiel aus Angulars Dokumenten an, $qaber ich denke, dass dies wahrscheinlich für Versprechen im Allgemeinen gilt. Das folgende Beispiel wird wörtlich aus ihren Dokumenten kopiert, wobei der Kommentar enthalten ist:

promiseB = promiseA.then(function(result) {
  return result + 1;
});

// promiseB will be resolved immediately after promiseA is resolved and its value
// will be the result of promiseA incremented by 1

Mir ist nicht klar, wie das funktioniert. Wenn ich .then()auf das Ergebnis des ersten .then()zurückgreifen kann, indem ich sie verkette, von dem ich weiß, dass ich es kann, dann promiseBist es ein Versprechungsobjekt vom Typ Object. Es ist kein Number. Was meinen sie also mit "sein Wert wird das Ergebnis von Versprechen sein, das um 1 erhöht wird"?

Soll ich so promiseB.valueoder so darauf zugreifen ? Wie kann der Erfolgsrückruf ein Versprechen zurückgeben UND "Ergebnis + 1" zurückgeben? Ich vermisse etwas.

temporärer_Benutzername
quelle
Ich habe eine verwandte Frage gestellt: Warum hat Promise keine get () -Funktion?
Roland
1
Beantwortet das deine Frage? Wie gebe ich die Antwort von einem asynchronen Aufruf zurück?
Heretic Monkey
Diese Frage ist 5 Jahre alt und hat eine akzeptierte Antwort ...
temporärer_Benutzername
@temporary_user_name: Es ist in Ordnung, dass Personen jederzeit enge Stimmen abgeben können, auch bei alten Fragen.
Halfer

Antworten:

140

promiseADie thenFunktion von 'gibt ein neues Versprechen ( promiseB) zurück, das sofort aufgelöst wird, nachdem promiseAes aufgelöst wurde. Sein Wert ist der Wert dessen, was von der darin enthaltenen Erfolgsfunktion zurückgegeben wird promiseA.

In diesem Fall promiseAwird mit einem Wert aufgelöst - resultund dann sofort promiseBmit dem Wert von aufgelöst result + 1.

Der Zugriff auf den Wert von promiseBerfolgt auf die gleiche Weise, wie wir auf das Ergebnis von zugegriffen haben promiseA.

promiseB.then(function(result) {
    // here you can use the result of promiseB
});

Edit Dezember 2019 : async/ awaitist jetzt Standard in JS, was eine alternative Syntax zu dem oben beschriebenen Ansatz ermöglicht. Sie können jetzt schreiben:

let result = await functionThatReturnsPromiseA();
result = result + 1;

Jetzt gibt es kein VersprechenB, da wir das Ergebnis von VersprechenA mit ausgepackt awaithaben und Sie direkt damit arbeiten können.

Allerdings awaitkann nur innerhalb einer verwendet werden asyncFunktion. Um etwas herauszuzoomen, müsste das Obige wie folgt enthalten sein:

async function doSomething() {
    let result = await functionThatReturnsPromiseA();
    return result + 1;
}
Nachshon Schwartz
quelle
2
Versprechen sind theoretisch ihre eigenen Objekte. Sie enthalten ein Ergebnis, auf das über die Erfolgsfunktion des Versprechens zugegriffen werden kann.
Nachshon Schwartz
2
Wenn Sie also mit dem Rückgabewert des asynchronen Rückrufs eines Versprechens arbeiten möchten, muss dies in einem anderen asynchronen Rückruf erfolgen. Macht Sinn. Ich hatte nach einer Möglichkeit gesucht, einen ultimativen primitiven Rückgabewert zu erhalten, aber ich nehme an, dass dies angesichts des Kontexts der Vernunft trotzen würde.
temporärer_Benutzername
2
@Aerovistae Tatsächlich führt ES6 Generatoren ein, die dies ermöglichen, und ES7 führt asynchrone Funktionen ein - beide geben Ihnen Syntaxzucker über Versprechen, die es wie synchronen Code aussehen lassen (indem Sie eine Zustandsmaschine im Hintergrund ausführen) - also halten Sie fest :)
Benjamin Gruenbaum
25

Wenn ein Versprechen gelöst / abgelehnt wird, ruft es seinen Erfolgs- / Fehlerbehandler auf:

var promiseB = promiseA.then(function(result) {
   // do something with result
});

Die thenMethode gibt auch ein Versprechen zurück: VersprechenB, das abhängig vom Rückgabewert des Erfolgs- / Fehlerbehandlers von VersprechenA aufgelöst / abgelehnt wird .

Es gibt drei mögliche Werte, die die Erfolgs- / Fehlerbehandlungsroutinen von VersprechenA zurückgeben können und die sich auf das Ergebnis von VersprechenB auswirken:

1. Return nothing --> PromiseB is resolved immediately, 
   and undefined is passed to the success handler of promiseB
2. Return a value --> PromiseB is resolved immediately,
   and the value is passed to the success handler of promiseB
3. Return a promise --> When resolved, promiseB will be resolved. 
   When rejected, promiseB will be rejected. The value passed to
   the promiseB's then handler will be the result of the promise

Mit diesem Verständnis können Sie Folgendes verstehen:

promiseB = promiseA.then(function(result) {
  return result + 1;
});

Der Then-Aufruf gibt Versprechen B sofort zurück. Wenn versprechenA gelöst ist, gibt es das Ergebnis an den Erfolgsbearbeiter von versprechenA weiter. Da der Rückgabewert das Ergebnis + 1 von VersprechenA ist, gibt der Erfolgshandler einen Wert zurück (Option 2 oben), sodass VersprechenB sofort aufgelöst wird und das Erfolgshandler von VersprechenB das Ergebnis + 1 von VersprechenA übergeben wird.

Pixelbits
quelle
4

.then Funktion von VersprechenB erhält, was von zurückgegeben wird .then Funktion von VersprechenA zurückgegeben wird.

Hier gibt VersprechenA eine Zahl zurück, die als numberParameter für die Erfolgsfunktion von VersprechenB verfügbar sein wird. die dann um 1 erhöht wird

harishr
quelle
3

Das Analysieren des Kommentars ein wenig anders als Ihr derzeitiges Verständnis könnte helfen:

// promiseB will be resolved immediately after promiseA is resolved

Dies besagt, dass dies promiseBein Versprechen ist, aber sofort nach der promiseALösung gelöst wird. Eine andere Sichtweise bedeutet, dass promiseA.then()ein Versprechen zurückgegeben wird, das zugewiesen ist promiseB.

// and its value will be the result of promiseA incremented by 1

Dies bedeutet, dass der promiseAaufgelöste Wert der Wert ist, promiseBder als successCallback-Wert erhalten wird:

promiseB.then(function (val) {
  // val is now promiseA's result + 1
});
Jason Cust
quelle
2

Die Antwort auf Pixelbits ist korrekt und Sie sollten immer verwenden, .then()um auf den Wert eines Versprechens im Produktionscode zuzugreifen.

Es gibt jedoch eine Möglichkeit, direkt nach dem Auflösen auf den Wert des Versprechens zuzugreifen, indem die folgende nicht unterstützte interne node.js-Bindung verwendet wird:

process.binding('util').getPromiseDetails(myPromise)[1]

WARNUNG: process.binding sollte niemals außerhalb des Kerns von nodejs verwendet werden, und das Kernteam von nodejs versucht aktiv, es zu verwerfen

https://github.com/nodejs/node/pull/22004 https://github.com/nodejs/node/issues/22064

Zeus Lalkaka
quelle
1

Dieses Beispiel finde ich selbsterklärend. Beachten Sie, wie das Warten auf das Ergebnis wartet und Sie das zurückgegebene Versprechen verpassen.

cryA = crypto.subtle.generateKey({name:'ECDH', namedCurve:'P-384'}, true, ["deriveKey", "deriveBits"])
Promise {<pending>}
cryB = await crypto.subtle.generateKey({name:'ECDH', namedCurve:'P-384'}, true, ["deriveKey", "deriveBits"])
{publicKey: CryptoKey, privateKey: CryptoKey}
Meister James
quelle
Dies muss eine asynchrone Funktion sein.
Samed
0
promiseA(pram).then(
     result => { 
     //make sure promiseA function allready success and response
     //do something here
}).catch(err => console.log(err)) => {
     // handle error with try catch
}
Tomnyson
quelle
1
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Alexander
0

Sie können dies einfach mit einer asynchronen Wartemethode in Javascript tun.

Unten finden Sie ein Beispiel für das Abrufen eines WebRTC-Versprechenswerts mithilfe eines Timeouts.

function await_getipv4(timeout = 1000) {
    var t1 = new Date();
    while(!window.ipv4) {
        var stop = new Date() - t1 >= timeout;
        if(stop) {
            console.error('timeout exceeded for await_getipv4.');
            return false;
        }
    }
    return window.ipv4;
}

function async_getipv4() {
    var ipv4 = null;
    var findIP = new Promise(r=>{var w=window,a=new (w.RTCPeerConnection||w.mozRTCPeerConnection||w.webkitRTCPeerConnection)({iceServers:[]}),b=()=>{};a.createDataChannel("");a.createOffer(c=>a.setLocalDescription(c,b,b),b);a.onicecandidate=c=>{try{c.candidate.candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g).forEach(r)}catch(e){}}})
    findIP.then(ip => window.ipv4 = ip);
    return await_getipv4();
};

Ochsengesicht
quelle
Es ist wichtig, dieses Snippet nicht hier, sondern in einem echten Browser auszuführen. Ich glaube, das liegt am Sandboxing.
OxFEEDFACE
0

Um in der Knoten-REPL eine DB-Verbindung zu erhalten, die den Wert eines Versprechens hat, habe ich den folgenden Ansatz gewählt:

let connection
try {
  (async () => {
    connection = await returnsAPromiseResolvingToConnection()
  })()
} catch(err) {
  console.log(err)
}

Die Zeile mit awaitwürde normalerweise ein Versprechen zurückgeben. Dieser Code kann in den Node REPL eingefügt oder, wenn er darin gespeichert index.jsist, in Bash with ausgeführt werden

node -i -e "$(< index.js)"

Dadurch bleiben Sie im Knoten REPL, nachdem Sie das Skript mit Zugriff auf die festgelegte Variable ausgeführt haben. Um zu bestätigen, dass die asynchrone Funktion zurückgegeben wurde, können Sie connectionbeispielsweise protokollieren und dann die Variable verwenden. Man möchte natürlich noch nicht damit rechnen, dass die asynchrone Funktion für Code im Skript außerhalb der asynchronen Funktion aufgelöst wird.

dmstack
quelle
0

Es gibt oben einige gute Antworten und hier ist die Version der ES6-Pfeilfunktion

var something = async() => {
   let result = await functionThatReturnsPromiseA();
   return result + 1;
}
roopa l
quelle
0

Ich lerne langsam Javascript-Versprechen. Standardmäßig geben alle asynchronen Funktionen ein Versprechen zurück. Sie können Ihr Ergebnis wie folgt verpacken:

(async () => {
//Optional "await"
  await yourAsyncFunctionOrPromise()
    .then(function (result) {
      return result +1;
    })
    .catch(function (error) {
      return error;
    })()
})

" Der Ausdruck" Warten " bewirkt, dass die Ausführung der asynchronen Funktion angehalten wird, bis ein Versprechen erfüllt ist (dh erfüllt oder abgelehnt wurde), und die Ausführung der asynchronen Funktion nach Erfüllung wieder aufgenommen wird. Bei Wiederaufnahme entspricht der Wert des Ausdrucks" Warten "dem des erfüllten Versprechens Wenn das Versprechen abgelehnt wird, löst der Ausdruck wait den abgelehnten Wert aus . "

Weitere Informationen zu Wartezeiten und Versprechungen finden Sie unter MDN Web Docs

LT-Sites
quelle
-5

Vielleicht hilft dieses kleine Typescript-Codebeispiel.

private getAccount(id: Id) : Account {
    let account = Account.empty();
    this.repository.get(id)
        .then(res => account = res)
        .catch(e => Notices.results(e));
    return account;
}

Hier repository.get(id)kehrt die a zurück Promise<Account>. Ich ordne es der Variablen accountinnerhalb der thenAnweisung zu.

aahoogendoorn
quelle
1
Ihr Code gibt ein Konto zurück, bevor das Versprechen aufgelöst werden kann. Aus diesem Grund wird Ihr Code abgelehnt. Ihr Code gibt immer Account.empty () zurück.
Felype