Why Is My Asynchronous Function Returning Promise { ≪Pending≫ } Instead of a Value

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

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

Async Function returns Promise pending

All async functions return a promise - always. Using await inside an async function suspends the execution of that function until the promise you are awaiting resolves or rejects, but an async function is not blocking to the outside world. An await does not suspend execution of the whole js interpreter.

At the point of the first await in the async function your function returns a promise back to the caller and the caller continues to execute. That promise is then resolved or rejects when the function eventually completes its work sometime in the future.

I don't understand why i get Promise { } since i used async/await

Because all async functions return a promise.


There are numerous issues in your code:

  1. Your getJSON() function has no return value. That means that the promise it returns resolves to undefined so there's not way to communicate back its value.
  2. await response.json needs to be await response.json().
  3. pokemonID should be passed as an argument, not just stuffed into a higher scoped variable.
  4. When calling getJSON(), you have to use .then() or await on it to get the resolved value from the returned promise.

You may also notice that your getJSON() function has no return value. That means that the promise it returns also resolves to undefined. And, await response.json needs to be await response.json().

Your code needs to be more like this:

async function getJSON(id) {
const response = await fetch('https://pokeapi.co/api/v2/pokemon/'+ id);
const json = await response.json();
return json;
}

const pokemonID = getRandomPokemon();
getJSON(pokemonID).then(data => {
console.log(data);
}).catch(err => {
console.log(err);
});

promise.then() returns Promise { pending }

Reduced your code by a bit instead of adding multiple promise resolution

  const fetch = require('node-fetch');

const everything = async () =>{
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const {id} = await response.json();
return `https://cdn.test.com/${id}`
}
everything().then((res)=>console.log(res));

Why is my function returning a Promise { pending } instead of my entries?

I would suggest you start by going full-on async/await instead of a mixture of that and then().

Starting at the getDistance method:

const getDistance = async (loc1, loc2) => {
const origins = encodeURI(`?origins=${loc1}`);
const destinations = encodeURI(`&destinations=${loc2}`);
const key = `&key=${process.env.VUE_APP_GOOGLE_MAPS_API_KEY}`;
const config = {
method: 'get',
url: `https://maps.googleapis.com/maps/api/distancematrix/json${origins}${destinations}${key}`,
headers: {}
};
try{
const response = await axios(config)
return response.data['rows'][0]['elements'][0]
}
catch(e){
console.log(e);
// return 0; // What should we return if there's an error?
}
}

Now the getAllDistances method becomes much easier to manage without all that nesting (caveat: I know nothing about knex, I'm only going by your code which as I commented seems odd that you repeatedly query all your companies.... but trying to replicate the same functionality that I think you have)

const getAllByDistance = async (location) => {
const entries = await knex("companies").select();

const results = [];
for(let i=0;i<entries.length;i++){
const company = entries[i];
const distance = await getDistance(location, `${company.street}, ${company.postcode} ${company.place}`);

const result = await knex('companies')
.select()
.where(parseInt(company.maximum_distance_km) >= parseInt(distance.toString().slice(0, -3)));
results.push(result);
}
return results;
}

The above has some drawbacks, mainly that it goes sequentially through the original list of companies getting the distance, and then loading up all the companies within that distance - but it will get you started to a more efficient algorithm i'm sure.

Why is my function returning Promise { pending }

const postCount = boards.map(async (boardI) => {
const posts = await Post.find({ board: boardI.slug });
return [boardI.slug, posts.length];
});

Since this is an async function, it will return a promise. map calls the function for each element of the array, gets the promises they return, and creates a new array containing those promises.

If you would like to wait for that array of promises to each finish, use Promise.all to combine them into a single promise, and then await the result.

const promises = boards.map(async (boardI) => {
const posts = await Post.find({ board: boardI.slug });
return [boardI.slug, posts.length];
});
const postCount = await Promise.all(promises);
console.log(postCount);


Related Topics



Leave a reply



Submit