¿Cómo acceder al valor de una promesa?

146

Estoy viendo este ejemplo de los documentos de Angular, $qpero creo que esto probablemente se aplica a las promesas en general. El siguiente ejemplo se copia literalmente de sus documentos con su comentario incluido:

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

No tengo claro cómo funciona esto. Si puedo invocar .then()el resultado del primero .then(), encadenándolos, lo que sé que puedo, entonces promiseBes un objeto de promesa, de tipo Object. No es un Number. Entonces, ¿qué quieren decir con "su valor será el resultado de la promesa A incrementada en 1"?

¿Se supone que debo acceder a eso promiseB.valueo algo así? ¿Cómo puede la devolución de llamada exitosa devolver una promesa Y devolver "resultado + 1"? Me falta algo

nombre_usuario_temporal
fuente
Hice una pregunta relacionada: ¿Por qué Promise no tiene una función get ()?
Roland
1
¿Responde esto a tu pregunta? ¿Cómo devuelvo la respuesta de una llamada asincrónica?
Heretic Monkey
Esta pregunta tiene 5 años y tiene una respuesta aceptada ...
temporary_user_name
@temporary_user_name: está bien que las personas emitan votos cercanos en cualquier momento, incluso en viejas preguntas.
Halfer

Respuestas:

141

promiseALa thenfunción devuelve una nueva promesa ( promiseB) que se resuelve inmediatamente después de que promiseAse resuelve, su valor es el valor de lo que se devuelve de la función de éxito dentro depromiseA .

En este caso promiseAse resuelve con un valor, resulty luego se resuelve inmediatamente promiseBcon el valor deresult + 1 .

El acceso al valor de promiseBse realiza de la misma manera que accedimos al resultado de promiseA.

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

Edición de diciembre de 2019 : async/ awaitahora es estándar en JS, lo que permite una sintaxis alternativa al enfoque descrito anteriormente. Ahora puedes escribir:

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

Ahora no hay promesaB, porque hemos desenvuelto el resultado del uso de la promesaA await, y puede trabajar con él directamente.

Sin embargo, awaitsolo se puede usar dentro de una asyncfunción. Entonces, para alejar un poco, lo anterior tendría que estar contenido así:

async function doSomething() {
    let result = await functionThatReturnsPromiseA();
    return result + 1;
}
Nachshon Schwartz
fuente
2
Las promesas son teóricamente sus propios objetos. contienen un resultado al que se puede acceder a través de la función de éxito de la promesa.
Nachshon Schwartz
2
Entonces, si desea trabajar con el valor de retorno de la devolución de llamada asíncrona de una promesa, debe hacerlo dentro de otra devolución de llamada asíncrona. Tiene sentido. Había estado buscando una forma de obtener un valor de retorno primitivo, pero supongo que eso desafiaría la razón dado el contexto.
temporary_user_name
2
@Aerovistae en realidad, ES6 presenta generadores que lo hacen posible y ES7 presenta funciones asíncronas, las cuales le brindan azúcar de sintaxis sobre las promesas que lo hacen parecer código síncrono (ejecutando una máquina de estado en segundo plano), así que agárrese fuerte :)
Benjamin Gruenbaum
25

Cuando una promesa se resuelve / rechaza, llamará a su controlador de éxito / error:

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

El thenmétodo también devuelve una promesa: promiseB, que se resolverá / rechazará según el valor de retorno del controlador de éxito / error de promiseA .

Hay tres valores posibles que los controladores de éxito / error de promesaA pueden devolver que afectarán el resultado de promesaB:

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

Armado con esta comprensión, puede dar sentido a lo siguiente:

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

La llamada entonces devuelve la promesa B inmediatamente. Cuando la promesa A se resuelva, pasará el resultado al controlador de éxito de promesa A. Como el valor de retorno es el resultado de la promesa A + 1, el controlador de éxito devuelve un valor (opción 2 anterior), por lo que la promesa B se resolverá de inmediato, y el controlador de éxito de la promesa B pasará el resultado de la promesa A + 1.

bits de píxel
fuente
4

.then función de promesa B recibe lo que devuelve .then función de promesa A.

aquí la promesa A está regresando es un número, que estará disponible como numberparámetro en la función de éxito de la promesa B. que luego se incrementará en 1

harishr
fuente
3

Analizar el comentario de manera un poco diferente a su comprensión actual podría ayudar:

// promiseB will be resolved immediately after promiseA is resolved

Esto indica que promiseBes una promesa, pero se resolverá inmediatamente después de que promiseAse resuelva. Otra forma de ver esto significa que promiseA.then()devuelve una promesa asignada promiseB.

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

Esto significa que el valor que promiseAresolvió es el valor que promiseBrecibirá como su valor SuccessCallback:

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

La respuesta de pixelbits es correcta y siempre debe usarla .then()para acceder al valor de una promesa en el código de producción.

Sin embargo, hay una forma de acceder al valor de la promesa directamente después de que se haya resuelto utilizando el siguiente enlace interno node.js no admitido:

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

ADVERTENCIA: process.binding nunca fue diseñado para usarse fuera del núcleo de nodejs y el equipo central de nodejs está buscando activamente desaprobarlo

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

Zeus Lalkaka
fuente
1

Este ejemplo me parece explicativo. Observe cómo la espera espera el resultado y, por lo tanto, pierde la Promesa que se devuelve.

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}
El maestro james
fuente
Esto tiene que estar en una función asíncrona.
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
fuente
1
Si bien este código puede responder la pregunta, proporcionar un contexto adicional sobre cómo y por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta.
Alexander
0

Puede hacerlo fácilmente utilizando un método de espera asíncrono en javascript.

A continuación se muestra un ejemplo de recuperación de un valor de promesa de WebRTC utilizando un tiempo de espera.

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

Cara de buey
fuente
Es importante ejecutar este fragmento no aquí, sino en un navegador real, creo que esto se debe al sandboxing.
OxFEEDFACE
0

En el Node REPL, para obtener una conexión de base de datos que era el valor de una promesa, tomé el siguiente enfoque:

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

La línea con awaitnormalmente devolvería una promesa. Este código se puede pegar en el Node REPL o, si se guarda, index.jsse puede ejecutar en Bash con

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

que te deja en el Nodo REPL después de ejecutar el script con acceso a la variable establecida. Para confirmar que la función asincrónica ha regresado, puede iniciar sesión, connectionpor ejemplo, y luego está listo para usar la variable. Por supuesto, uno no querría contar con que la función asincrónica se resuelva aún para cualquier código en el script fuera de la función asincrónica.

dmstack
fuente
0

Hay una buena respuesta arriba y aquí está la versión de la función de flecha ES6

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

Aprendo lentamente las promesas de JavaScript, de forma predeterminada todas las funciones asíncronas devuelven una promesa, puede ajustar su resultado como:

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

" La expresión de espera hace que la ejecución de la función asíncrona se detenga hasta que se liquide una Promesa (es decir, cumplida o rechazada), y que reanude la ejecución de la función asíncrona después del cumplimiento. Cuando se reanuda, el valor de la expresión de espera es el de la Promesa cumplida Si se rechaza la promesa, la expresión de espera arroja el valor rechazado ".

Lea más sobre la espera y las promesas en MDN Web Docs

Sitios LT
fuente
-5

Tal vez este pequeño ejemplo de código mecanografiado ayude.

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

Aquí el repository.get(id)devuelve a Promise<Account>. Lo asigno a la variable accountdentro de la thendeclaración.

aahoogendoorn
fuente
1
Su código devuelve la cuenta antes de que se pueda resolver la promesa y es por eso que se rechaza, su código siempre devuelve Account.empty ();
Felype