In the following code I wrote to get data from an API, I am getting promises as an output instead of data. What am I missing? Can someone please help?
const axios = require('axios');
const ageFinder = async (userName) => {
try {
let userDetails =await axios.get(`https://hacker-news.firebaseio.com/v0/user/${userName}.json`)
let user =userDetails.data
return user
} catch(err) {
console.log(err.message)
}
}
console.log(ageFinder("someUser"))
As per the MDN page on async functions, any function declared async returns a promise, which resolves whatever the function returns or rejects with an error, if any is encountered within the function (see "Return Value" section of page linked above).
So you will need to put your function call ageFinder("someUser") in another async function and await its result before logging, or you may use .then().
An async function always returns a promise. To use it you need to await it in another async function. If you do not want to await in another async function you may use it with the alternative then method. For example:
ageFinder("someUser")
.then((response) => {
console.log(response);
}).
.catch((err) => {
console.log(err);
});
Related
Trying to make an API request with error checking and then be able to use the data from the API outside the async function. This is returning a pending promise right now. Not sure how get useable data out of the API that I can then further use throughout the program. Suggestions?
const fetch = require('node-fetch')
const url = 'https://employeedetails.free.beeceptor.com/my/api/path'
async function getData(url){
try {
const response = await fetch(url)
if (!response.ok) {
throw new Error ("why did I become a software engineer?");
}
else {
return await response.json();
}
}
catch (error) {
console.log(error);
}
}
const data = getData(url);
console.log(data);
async functions return a promise. To get the usable data you will have to either await getData(url) (create another async function for this) or in your example you can write:
getData(url).then(data => console.log(data);
I think the problem here is that the async function is returning a promise so you should add another asyn function to get that data, or maybe you should add a global variable before the function and then change its value
This question already has answers here:
async/await implicitly returns promise?
(5 answers)
Closed 1 year ago.
When I console.log(data), I log the information I need, but if return the value of data in getWeather(), it just returns a pending promise. I have tried many things, but none have worked so far. I'll leave my broken code below.
const axios = require('axios');
const getWeather = async () => {
try {
let response = await axios.get(
'http://api.openweathermap.org/data/2.5/forecast?id=524901&appid={apiKey}'
);
let data = response.data;
return data;
} catch (e) {
console.log(e);
}
};
async function returnAsync() {
const x = await getWeather();
return x;
}
console.log(getWeather()); // returns a pending promise
console.log('check ', returnAsync()); // also returns a pending promise
async functions must return a promise. (they implicitly return Promise<void> instead of void!)
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 promise.
For example, the following:
async function foo() {
return 1
}
...is equivalent to:
function foo() {
return Promise.resolve(1)
}
Source
This could be to do with the fact that you're trying to call an async function inside of a synchronous function. It's quite a common mistake to make, so don't fret. Typically if you think about the structure, the console logs could technically be run before the async function has completed. That's why we have "callback functions" which basically just run as soon as the async returns a value.
Axios has a really neat way to use these callbacks which is just using the .then() function.
So try this out and see if it works:
const axios = require('axios');
const getWeather = async () => {
axios.get('http://api.openweathermap.org/data/2.5/forecast?id=524901&appid={apiKey}')
.then(json => console.log(json))
.catch(error => console.log(error))
};
getWeather();
Because you're trying to call the get request inside of an async function, you cannot then grab the data in a synchronous function.
//const getWeather = async () => {...
An async function's return value will be a Promise which will be resolved with the value returned by the async function, or rejected with an exception thrown from, or uncaught within, the async function.
check more at
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
My 2 API calls happen to be at the same time, where the response of API1 is to be sent as a request parameter to API2. But, the value goes as undefined because it isn't fetched till that time. Is there any way this can be solved in react.
There are multiple ways to solve this problem, I will explain one of the latest as well most sought after ways of solving the problem.
I am sure you would have heard of async/await in JavaScript, if you haven't I would suggest you to go through an MDN document around the topic.
There are 2 keywords here, async && await, let's see each of them one by one.
Async
Adding async before any function means one simple thing, instead of returning normal values, now the function will return a Promise
For example,
async function fetchData() {
return ('some data from fetch call')
}
If you run the above function in your console simply by fetchData(). You'd see that instead of returning the string value, this function interestingly returns a Promise.
So in a nutshell async ensures that the function returns a promise, and wraps non-promises in it.
Await
I am sure by now, you would have guessed why we use keyword await in addition to async, simply because the keyword await makes JavaScript wait until that promise (returned by the async function) settles and returns its result.
Now coming on to how could you use this to solve your issue, follow the below code snippet.
async function getUserData(){
//make first request
let response = await fetch('/api/user.json');
let user = await response.json();
//using data from first request make second request/call
let gitResponse = await fetch(`https://api.github.com/users/${user.name}`)
let githubUser = await gitResponse.json()
// show the avatar
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// wait 3 seconds
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
As you can see the above code is quite easy to read and understand. Also refer to THIS document for more information on async/await keyword in JavaScript.
Asyn/await solves your problem:
const requests = async () =>{
const response1 = await fetch("api1")
const result1 = await response1.json()
// Now you have result from api1 you might use it for body of api2 for exmaple
const response2 = await fetch("api2", {method: "POST", body: result1})
const result2 = await response1.json()
}
If you're using react hooks, you can use a Promise to chain your API calls in useEffect
useEffect(() => {
fetchAPI1().then(fetchAPI2)
}, [])
relevant Dan Abramov
fetch(api1_url).then(response => {
fetch(api2_url, {
method: "POST",
body: response
})
.then(response2 => {
console.log(response2)
})
})
})
.catch(function (error) {
console.log(error)
});
or if using axios
axios.post(api1_url, {
paramName: 'paramValue'
})
.then(response1 => {
axios.post(api12_url, {
paramName: response1.value
})
.then(response2 => {
console.log(response2)
})
})
.catch(function (error) {
console.log(error);
});
I've been reading up on promises for a few hours and I'm loosing my mind here. According to what I've read in SO and articles on google. To get the value of a response in a variable I have to use async and await. So going that route I've written this code:
async function getZpid() {
let response = await function getZillowZpid(){
zillow.get('GetSearchResults', parameters)
.then(results => {
let zpidResponse = results.response.results.result[0].zpid;
console.log("i ran");
return zpidResponse;
});
}
}
getZpid();
Here I would expect that when getZpid() runs "response" would wait for the function get ZillowZpid to be done. Once it would be completed it would console.log "i ran" and then return the zpidResponse.
I get no error but the console.log never appears. Ultimately the console.log is just a test what I am trying to do is get zpidResponse in to a variable I could use outside the function. Any help would be greatly appreciated!
You are defining an extraneous function with await function getZillowZpid() which you never call. This is why you see no error or results. If you log the variable response in your function above you will see that it is something [Function: getZillowZpid], you've defined a function and assigned it to response which is certainly not what you want.
Since zillow.get returns a promise, you can just await that. Here's an example with a mocked zillow object:
// fake the zillow object
let zillow = {
get() {
return Promise.resolve({response: {results: {result: [{zpid: "Some data"}]}}})
}
}
async function getZpid() {
let parameters = {}
// zillow.get returns a promise, you can use await to get the returned value
let response = await zillow.get('GetSearchResults', parameters)
.then(results => {
let zpidResponse = results.response.results.result[0].zpid;
console.log("i ran");
return zpidResponse;
});
console.log(response)
}
getZpid();
FYI, if you're using async/await it's cleaner to avoid the then() although you still should add some error-checking:
// fake zillow
let zillow = {
get() {
return Promise.resolve({response: {results: {result: [{zpid: "Some data"}]}}})
}
}
async function getZpid() {
let parameters = 0
let response = await zillow.get('GetSearchResults', parameters)
let zpidResponse = response.response.results.result[0].zpid;
console.log(zpidResponse)
return zpidResponse
}
getZpid();
I'm really confused about why I can not return the JSON result from amazonMws.products.search() and could use some help understanding what is going on. When I write it this way gives me undefined:
function listMatchingProducts(query) {
const options = {
Version: VERSION,
Action: 'ListMatchingProducts',
MarketplaceId: MARKET_PLACE_ID,
SellerId: SELLER_ID,
Query: query
}
amazonMws.products.search(options, (err, res) => {
if(err){
throw(err)
return
}
return res
})
}
I also get undefined when using amazonMws.products.search().then().catch() as well.
If I return amazonMws.products.search() I get a promise back instead of the result.
Inside of the callbacks if I console.log(res) I get back the JSON result I'm expecting. So this led me to believe I need to use async await I think, but this results in Promise { <pending> }:
async function listMatchingProducts(query) {
const options = {
Version: VERSION,
Action: 'ListMatchingProducts',
MarketplaceId: MARKET_PLACE_ID,
SellerId: SELLER_ID,
Query: query
}
return await amazonMws.products.search(options)
.then(res => {
return res
})
.catch(e => errorHandler(e))
}
I am totally lost, so if someone could explain to me what is going on, that would be greatly appreciated.
The amazonMws.products.search function is asynchronous, meaning that it will give you a value later, and because of this, you can't get the value now. Instead, you'll have to say what you want to do later when you receive the value.
This is what returning the promise does. The promise itself is the representation of this value that you'll receive later.
function listMatchingProducts(query) {
const options = {
Version: VERSION,
Action: 'ListMatchingProducts',
MarketplaceId: MARKET_PLACE_ID,
SellerId: SELLER_ID,
Query: query
}
return amazonMws.products.search(options)
}
Then, when calling the function, attach a handler to the promise.
listMatchingProducts(someQuery)
.then(result => {/* do something with result */})
.catch(error => {/* handle the error */})
And, though you don't need to use async await here, it can make the code look a little nicer in some situations, as though it were synchronous. Here's what calling the above function would look like with async await:
async function getProducts() {
try {
const result = await listMatchingProducts(someQuery)
// do something with result
} catch (error) {
// handle the error
}
}
And, as usual, always consult the docs for any detail you're confused about:
Using promises
await keyword
function listMatchingProducts(query) {
const options = {
Version: VERSION,
Action: 'ListMatchingProducts',
MarketplaceId: MARKET_PLACE_ID,
SellerId: SELLER_ID,
Query: query
}
return amazonMws.products.search(options); //returns a promise
}
As others have pointed out, Promises just don’t work the way you think they do.
See my answer to function returning too early before filter and reduce finish for a (hopefully) clear explanation of the problem you face.