Why is my asynchronous function returning Promise { <pending> } instead of a value?

Src picture Src · Aug 11, 2016 · Viewed 264.1k times · Source

My code:

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

And when i try to run something like this:

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

I'm getting:

Promise { <pending> }

But why?

My main goal is to get token from google.login(data.username, data.password) which returns a promise, into a variable. And only then preform some actions.

Answer

Bamieh picture Bamieh · Aug 11, 2016

The promise will always log pending as long as its results are not resolved yet. You must call .then on the promise to capture the results regardless of the promise state (resolved or still pending):

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"
})

Why is that?

Promises are forward direction only; You can only resolve them once. The resolved value of a Promise is passed to its .then or .catch methods.

Details

According to the Promises/A+ spec:

The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x). If x is a thenable, it attempts to make promise adopt the state of x, under the assumption that x behaves at least somewhat like a promise. Otherwise, it fulfills promise with the value x.

This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant then method. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonable then methods.

This spec is a little hard to parse, so let's break it down. The rule is:

If the function in the .then handler returns a value, then the Promise resolves with that value. If the handler returns another Promise, then the original Promise resolves with the resolved value of the chained Promise. The next .then handler will always contain the resolved value of the chained promise returned in the preceding .then.

The way it actually works is described below in more detail:

1. The return of the .then function will be the resolved value of the promise.

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. If the .then function returns a Promise, then the resolved value of that chained promise is passed to the following .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"
  });