Come accedere al valore di una promessa?


146

Sto guardando questo esempio dai documenti di Angular per $qma penso che questo probabilmente si applica alle promesse in generale. L'esempio seguente è copiato letteralmente dai loro documenti con il loro commento incluso:

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

Non sono chiaro come funzioni. Se posso invocare .then()il risultato del primo .then(), incatenandoli, che so di poter fare, allora promiseBè un oggetto promettente, di tipo Object. Non è un Number. Quindi cosa intendono per "il suo valore sarà il risultato di promiseA incrementato di 1"?

Dovrei accedervi come promiseB.valueo qualcosa del genere? Come può il callback di successo restituire una promessa E restituire "risultato + 1"? Mi manca qualcosa.


Ho posto una domanda correlata: Perché Promise non ha una funzione get ()?
Roland,


Questa domanda ha 5 anni e ha una risposta accettata ...
temporaneo

@temporary_user_name: va bene per le persone esprimere voti stretti in qualsiasi momento, anche su vecchie domande.
Halfer

Risposte:


141

promiseALa thenfunzione restituisce una nuova promessa ( promiseB) che viene immediatamente risolta dopo che promiseAè stata risolta, il suo valore è il valore di ciò che viene restituito dalla funzione di successo all'interno promiseA.

In questo caso promiseAviene risolto con un valore, resultquindi si risolve immediatamente promiseBcon il valore di result + 1.

L'accesso al valore di promiseBè fatto nello stesso modo in cui abbiamo avuto accesso al risultato promiseA.

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

Modifica dicembre 2019 : async/ awaitè ora standard in JS, che consente una sintassi alternativa all'approccio sopra descritto. Ora puoi scrivere:

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

Ora non c'è promessa B, perché non abbiamo scartato il risultato dall'uso promessoA awaite puoi lavorarci direttamente.

Tuttavia, awaitpuò essere utilizzato solo all'interno di una asyncfunzione. Quindi per ridurre leggermente, quanto sopra dovrebbe essere contenuto in questo modo:

async function doSomething() {
    let result = await functionThatReturnsPromiseA();
    return result + 1;
}

2
Le promesse sono teoricamente i loro stessi oggetti. contengono un risultato a cui è possibile accedere tramite la funzione di successo della promessa.
Nachshon Schwartz,

2
Quindi, se si desidera lavorare con il valore restituito del callback asincrono di una promessa, è necessario farlo all'interno di un altro callback asincrono. Ha senso. Stavo cercando un modo per ottenere un valore di ritorno primitivo finale, ma suppongo che sfiderebbe la ragione dato il contesto.
temporaneo

2
@Aerovistae in realtà, ES6 introduce generatori che lo rendono possibile ed ES7 introduce funzioni asincrone - entrambi i quali ti danno zucchero di sintassi su promesse che lo fanno sembrare un codice sincrono (eseguendo una macchina a stati in background) - quindi tieni duro :)
Benjamin Gruenbaum,

25

Quando una promessa viene risolta / rifiutata, chiamerà il suo gestore di successo / errore:

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

Il thenmetodo restituisce anche una promessa: promiseB, che verrà risolta / rifiutata in base al valore restituito dal gestore esito positivo / errore di promiseA .

Esistono tre possibili valori che possono essere restituiti dai gestori di successo / errore di promiseA che influiranno sul risultato di promiseB:

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

Grazie a questa comprensione, puoi dare un senso a quanto segue:

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

La chiamata quindi restituisce promiseB immediatamente. Quando promiseA viene risolto, passerà il risultato al gestore del successo di promiseA. Poiché il valore restituito è il risultato di promessa + 1, il gestore del successo restituisce un valore (opzione 2 sopra), quindi promiseB si risolverà immediatamente e il gestore del successo di promiseB verrà passato il risultato di promA + 1.


4

.thenLa funzione di promiseB riceve ciò che viene restituito dalla .thenfunzione di promiseA.

qui promiseA sta tornando è un numero, che sarà disponibile come numberparametro nella funzione di successo di promiseB. che verrà quindi incrementato di 1


3

Analizzare il commento in modo leggermente diverso rispetto alla tua attuale comprensione potrebbe aiutare:

// promiseB will be resolved immediately after promiseA is resolved

Questo afferma che promiseBè una promessa ma verrà risolto immediatamente dopo la promiseArisoluzione. Un altro modo di vedere questo significa che promiseA.then()restituisce una promessa a cui è assegnato promiseB.

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

Ciò significa che il valore che è stato promiseArisolto è il valore che promiseBriceverà come valore successCallback:

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

2

la risposta di pixelbits è corretta e dovresti sempre usare .then()per accedere al valore di una promessa nel codice di produzione.

Tuttavia, esiste un modo per accedere al valore della promessa direttamente dopo che è stato risolto utilizzando il seguente binding node.js interno non supportato:

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

ATTENZIONE: process.binding non è mai stato pensato per essere utilizzato al di fuori del core nodejs e il team principale di nodejs sta attivamente cercando di deprecarlo

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


1

Questo esempio lo trovo autoesplicativo. Nota come attende il risultato e così perdi la promessa di essere restituita.

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}

Questo deve essere in una funzione asincrona.
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
}

1
Mentre questo codice può rispondere alla domanda, fornendo un contesto aggiuntivo riguardo a come e perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
Alexander,

0

Puoi farlo facilmente usando un metodo di attesa asincrono in javascript.

Di seguito è riportato un esempio che recupera un valore di promessa WebRTC utilizzando un timeout.

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();
};


È importante eseguire questo snippet non qui ma in un browser reale, credo che ciò sia dovuto al sandboxing.
OxFEEDFACE,

0

Nel Node REPL, per ottenere una connessione DB che era il valore di una promessa, ho adottato il seguente approccio:

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

La linea con awaitnormalmente restituirebbe una promessa. Questo codice può essere incollato nel REPL del nodo o se salvato in index.jsesso può essere eseguito in Bash con

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

che ti lascia nel REPL del nodo dopo aver eseguito lo script con accesso alla variabile set. Per confermare che la funzione asincrona è tornata, è possibile accedere connectionad esempio e quindi si è pronti per utilizzare la variabile. Uno ovviamente non vorrebbe fare affidamento sulla risoluzione della funzione asincrona per qualsiasi codice nello script al di fuori della funzione asincrona.


0

Ci sono alcune buone risposte sopra ed ecco la versione della funzione Freccia ES6

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

0

Sono uno studente lento di promesse javascript, per impostazione predefinita tutte le funzioni asincrone restituiscono una promessa, è possibile racchiudere il risultato come:

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

" L'espressione waitit fa sospendere l'esecuzione della funzione asincrona fino a quando una Promessa non viene stabilita (ovvero, adempiuta o respinta) e riprende l'esecuzione della funzione asincrona dopo l'adempimento. Quando viene ripresa, il valore dell'espressione waitit è quello della Promessa adempiuta Se la Promessa viene rifiutata, l'espressione wait attende il valore rifiutato . "

Maggiori informazioni su attendono e promesse su MDN Web Docs


-5

Forse questo piccolo esempio di codice dattiloscritto aiuterà.

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

Qui i repository.get(id)ritorni a Promise<Account>. Lo assegno alla variabile accountall'interno thendell'istruzione.


1
Il tuo codice restituisce l'account prima che il promisse possa essere risolto ed è per questo che è votato in ribasso, il tuo codice restituisce sempre Account.empty ();
Felype,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.