¿Por qué mi función asincrónica devuelve Promise { <pending> } en lugar de un valor?

Resuelto Src asked hace 8 años • 9 respuestas

Mi código:

let AuthUser = data => {
  return google.login(data.username, data.password).then(token => { return token } )
}

Y cuando intento ejecutar algo como esto:

let userToken = AuthUser(data)
console.log(userToken)

Me estoy poniendo:

Promise { <pending> }

¿Pero por qué?

Mi objetivo principal es convertir el token google.login(data.username, data.password)que devuelve una promesa en una variable. Y sólo entonces realizar algunas acciones.

Src avatar Aug 11 '16 05:08 Src
Aceptado

La promesa siempre quedará pendiente mientras sus resultados no se resuelvan aún. Debe invocar .thenla promesa para capturar los resultados independientemente del estado de la promesa (resuelta o aún pendiente):

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = AuthUser(data)
console.log(userToken) // Promise { <pending> }

userToken.then(function(result) {
   console.log(result) // "Some User token"
})

¿Porqué es eso?

Las promesas son sólo dirección hacia adelante; Sólo puedes resolverlos una vez. El valor resuelto de a Promisese pasa a sus métodos .theno .catch.

Detalles

Según la especificación Promises/A+:

El procedimiento de resolución de promesa es una operación abstracta que toma como entrada una promesa y un valor, que denotamos como [[Resolve]](promesa, x). Si x es un entoncesable, intenta hacer que la promesa adopte el estado de x, bajo el supuesto de que x se comporta al menos de alguna manera como una promesa. En caso contrario, cumple la promesa con el valor x.

Este tratamiento de thenables permite que las implementaciones de promesas interoperen, siempre que expongan un método then compatible con Promises/A+. También permite que las implementaciones de Promises/A+ "asimilen" implementaciones no conformes con métodos entonces razonables.

Esta especificación es un poco difícil de analizar, así que analicémosla. La regla es:

Si la función en el .thencontrolador devuelve un valor, entonces se Promiseresuelve con ese valor. Si el controlador devuelve otro Promise, entonces el original Promisese resuelve con el valor resuelto del encadenado Promise. El siguiente .thencontrolador siempre contendrá el valor resuelto de la promesa encadenada devuelta en el anterior .then.

La forma en que realmente funciona se describe a continuación con más detalle:

1. El retorno de la .thenfunción será el valor resuelto de la promesa.

function initPromise() {
  return new Promise(function(res, rej) {
    res("initResolve");
  })
}

initPromise()
  .then(function(result) {
    console.log(result); // "initResolve"
    return "normalReturn";
  })
  .then(function(result) {
    console.log(result); // "normalReturn"
  });

2. Si la .thenfunción devuelve a Promise, entonces el valor resuelto de esa promesa encadenada se pasa al siguiente .then.

function initPromise() {
  return new Promise(function(res, rej) {
    res("initResolve");
  })
}

initPromise()
  .then(function(result) {
    console.log(result); // "initResolve"
    return new Promise(function(resolve, reject) {
       setTimeout(function() {
          resolve("secondPromise");
       }, 1000)
    })
  })
  .then(function(result) {
    console.log(result); // "secondPromise"
  });
Bamieh avatar Aug 10 '2016 22:08 Bamieh

Me encontré con el mismo problema y la respuesta al problema es que, desde ES2017, las awaitfunciones pueden simplemente devolver el valor (a partir de ahora, solo funciona en asyncfunciones), como:

let AuthUser = function(data) {
  return google.login(data.username, data.password)
}

let userToken = await AuthUser(data)
console.log(userToken) // your data
Marius Seack avatar Dec 01 '2018 13:12 Marius Seack

Si esa situación ocurre para múltiples valores como una matriz.

[ 
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]

Puede utilizar Promise.all()esto para resolver todas las promesas.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Hasan Tezcan avatar May 30 '2021 10:05 Hasan Tezcan