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

2022-08-30 00:52:22

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 which returns a promise, into a variable. And only then preform some actions.google.login(data.username, data.password)


答案 1

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

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 is passed to its or methods.Promise.then.catch

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 handler returns a value, then the resolves with that value. If the handler returns another , then the original resolves with the resolved value of the chained . The next handler will always contain the resolved value of the chained promise returned in the preceding ..thenPromisePromisePromisePromise.then.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"
  });

答案 2

I know this question was asked 2 years ago, but I run into the same issue and the answer for the problem is since ES2017, that you can simply the functions return value (as of now, only works in functions), like:awaitasync

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

let userToken = await AuthUser(data)
console.log(userToken) // your data