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:
- Your
getJSON()
function has no return value. That means that the promise it returns resolves toundefined
so there's not way to communicate back its value. await response.json
needs to beawait response.json()
.pokemonID
should be passed as an argument, not just stuffed into a higher scoped variable.- When calling
getJSON()
, you have to use.then()
orawait
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
How to Make Console.Log Show the Current State of an Object
Controller Not a Function, Got Undefined, While Defining Controllers Globally
Why This JavaScript Regex Doesn't Work
Settimeout Calls Function Immediately Instead of After Delay
How to Check For a #Hash in a Url Using JavaScript
Check If an Array Contains Any Element of Another Array in JavaScript
Changing the Image Source Using Jquery
How to Set the Caret (Cursor) Position in a Contenteditable Element (Div)
Find an Element in Dom Based on an Attribute Value
How to Avoid 'Cannot Read Property of Undefined' Errors
Ecmascript Template Literals Like 'Some ${String}' Are Not Working
Sum JavaScript Object Propertya Values With the Same Object Propertyb in an Array of Objects
Backslashes - Regular Expression - JavaScript
Graph Visualization Library in JavaScript