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

convert promise to async/await
async function
async arrow function
async/await vs promises
promise { <pending> }
what is async
nodejs async/await
async/await try/catch

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.

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

Why is my asynchronous function returning Promise { <pending , An async function simply implies that a promise will be returned and if the async keyword allows us to write a function that returns a promise,  Since the return value of an async function is always wrapped in Promise.resolve, return await doesn’t actually do anything except add extra time before the overarching Promise resolves or rejects. The only valid exception is if return await is used in a try/catch statement to catch errors from another Promise-based function.

I know this question was asked 2 years ago, but I run into the same issue and the answer for the problem is since ES6, that you can simply await the functions return value, like:

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

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

Async and Await in JavaScript, the extension to a promise., Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a  Does this helper function need to be declared as asynchronous to itself return a promise? No. async functions always return promises, even if the return statement returns something that is not a promise. async functions let you manage other promises inside them using await. You can explicitly return a promise from any function.

The then method returns a pending promise which can be resolved asynchronously by the return value of a result handler registered in the call to then, or rejected by throwing an error inside the handler called.

So calling AuthUser will not suddenly log the user in synchronously, but returns a promise whose then registered handlers will be called after the login succeeds ( or fails). I would suggest triggering all login processing by a then clause of the login promise. E.G. using named functions to highlight the sequence of flow:

let AuthUser = data => {   // just the login promise
  return google.login(data.username, data.password);
};

AuthUser(data).then( processLogin).catch(loginFail);

function processLogin( token) {
      // do logged in stuff:
      // enable, initiate, or do things after login
}
function loginFail( err) {
      console.log("login failed: " + err);
}

async function, In fact every async function you write will return a promise, and every single thing you await will ordinarily be a promise. Why am I emphasizing  The return value will always be a promise. If you don't explicitly return a promise, the value you return will automatically be wrapped in a promise. async function increment(num) { return num + 1; } // Even though you returned a number, the value is // automatically wrapped in a promise, so we call // `then` on it to access the returned value.

See the MDN section on Promises. In particular, look at the return type of then().

To log in, the user-agent has to submit a request to the server and wait to receive a response. Since making your application totally stop execution during a request round-trip usually makes for a bad user experience, practically every JS function that logs you in (or performs any other form of server interaction) will use a Promise, or something very much like it, to deliver results asynchronously.

Now, also notice that return statements are always evaluated in the context of the function they appear in. So when you wrote:

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

the statement return token; meant that the anonymous function being passed into then() should return the token, not that the AuthUser function should. What AuthUser returns is the result of calling google.login(username, password).then(callback);, which happens to be a Promise.

Ultimately your callback token => { return token; } does nothing; instead, your input to then() needs to be a function that actually handles the token in some way.

Understand promises before you start using async/await, Async functions always return a promise, whether you use await or not. That promise resolves with whatever the async function returns,  Putting the keyword async before a function tells the function to return a Promise. If the code returns something that is not a Promise, then JavaScript automatically wraps it into a resolved promise with that value e.g when it returns an AsyncFunction object: async function oddNumber () { return 7; }

Your Promise is pending, complete it by

userToken.then(function(result){
console.log(result)
})

after your remaining code. All this code does is that .then() completes your promise & captures the end result in result variable & print result in console. Keep in mind, you cannot store the result in global variable. Hope that explanation might help you.

Async functions, async functions return promises. you need to do const data = await getData() -- unless you intend to set data at the top level of the code,  Understand promises before you start using async/await. In fact every async function you write will return a promise, and every single thing you await will ordinarily be a promise.

Async / Await returning Promise <pending> instead of values · Issue , Promise-Returning. Async functions always return a promise, so the following may not produce the result you're after: async function  An async function is a function declared with the keyword async and therefore compiled such that the return value of the function is an implicit (i.e. unnamed) promise which, upon resolution, will provide the value returned by the "apparent" function. The promise (like any promise) will complete in a stack frame different from, and later than, the stack frame in which it was created.

Exploring Async/Await Functions in JavaScript ← Alligator.io, 4 Returned Promises are not wrapped #. Resolving a Promise is a standard operation. return uses it to resolve the Promise p of an async function. That means:. If createAudioFileAsync() were rewritten to return a promise, using it could be as simple as this: createAudioFileAsync(audioSettings).then(successCallback, failureCallback); That's shorthand for: const promise = createAudioFileAsync(audioSettings); promise.then(successCallback, failureCallback); We call this an asynchronous function call. This convention has several advantages.

5. Async functions, JavaScript ensures that an async function always returns a promise. You can only use the await operator in the body of an async function. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.

Comments
  • @LoïcFaure-Lacroix , see this article: medium.com/@bluepnume/…
  • @LoïcFaure-Lacroix look at getFirstUser function
  • So what about it? It's a function returning a promise.
  • @LoïcFaure-Lacroix so you mean even in that example we need to use then to access the data promise returning in getFirstUser function?
  • In that exemple yes, the only other way is to use the ES7 syntax "await" that seems to resolve stop the execution of the current context to await the result of the promise. If you read the article you'll see it. But since ES7 is probably almost supported nowhere yet, yes. The "then" is pretty much it.
  • Your first one is not working. Uncaught SyntaxError: Unexpected token .. The second one needs a return for Promise
  • @zamil you have to invoke the function, like in the second example. you cant .then on a uninvoked function. updated the answer
  • I'm bookmarking this so that I can keep it forever. I have been working a VERY long time to find truly clear and readable rules of how to actually build promises. Your blockquote of Promises/A+ spec is a perfect example of why it's been a PITA to self teach promises. It's also the ONLY time I've seen setTimeout used where it didn't confuse the lesson itself. And excellent reference, thank you.
  • @monsto thank you :)
  • You don't need the .then(token => return token), that's just an unnecessary passthrough. Simply return the the google login call.
  • This answer is unrelated to the question. The problem of the original poster has nothing to do with ES6' async/await. Promises existed before this new syntactic sugar was introduced in ECMAScript 2017 and they used Promises "under the hood". See MDN on async/await.
  • For ES8 / Nodejs, errors are thrown if you use await outside of an async function. Perhaps the better example here would be to make the AuthUser function async, that then ends with return await google.login(...);
  • @Src I wrote my answer before the asker clarified that they were looking for a way to synchronously return a value, and without making assumptions about their dev environment or language version beyond what could be inferred by the code snippet -- that is, it's safe to assume ES6, but not necessarily ES7.