pending promise inside async/await - javascript

I wast trying to fetch some data in componentDidMount and then set it to state, wrote an async await function for the same. But if i was trying to set the state with the values right after await, the value was getting set to a pending promise but console logging would give the correct output.
For that reason i called the getData().then() to set the data, why it was giving pending promise can someone clear the concept out here?
componentDidMount() {
async function getData() {
const baseUrl = `https://........`;
const response = await fetch(baseUrl);
if (response.status === 200) {
const json = await response.json();
const { data } = json;
//console.log(data) =>correct output
return data;
}
return null;
}
getData().then(data => {
this.setState({ names: data });
});
}

You can simply do it like that:
componentDidMount() {
const baseUrl = `https://........`;
fetch(baseUrl)
.then((response) => response.json())
.then(result => {
this.setState({ names: result.data});
});
}

getData is an async function that you syncronize your fetch call inside. So it returns a promise. You're console logging inside that function after response fetched. So it logs the data.
You can think it as Fetch function that you use, you're awaiting it because it's a async function and you should await for the response. It's the same for the getData too. No matter how you wait, use then or await.

Related

being able to use data with fetch api request and error checking

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

Why don't both functions log the same result?

The 1st example logs the resolved value of the promise from the fetch.
The 2nd example logs the pending promise object to the console which I then have to .then((res) => {console.log(res)}) to get the resolved value.
I'm using async functions so I thought both examples were equivalent...?
I have not shown my API key but it works when I use it in the code.
1st Example:
const apiKey = 'somekey';
const city = 'Berlin'
const getWeather = async (cityArg, apiKeyArg) => {
let city = cityArg;
let apiKey = apiKeyArg;
try{
const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}`);
if(response.ok) {
let jsonResponse = await response.json();
console.log(jsonResponse);
//return jsonResponse;
}
} catch(error) {
console.log(error);
}
}
getWeather(city, apiKey);
//console.log(getWeather(city, apiKey));
2nd Example:
const apiKey = 'somekey';
const city = 'Berlin'
const getWeather = async (cityArg, apiKeyArg) => {
let city = cityArg;
let apiKey = apiKeyArg;
try{
const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}`);
if(response.ok) {
let jsonResponse = await response.json();
//console.log(jsonResponse);
return jsonResponse;
}
} catch(error) {
console.log(error);
}
}
//getWeather(city, apiKey);
console.log(getWeather(city, apiKey));
The reason is that you are awaiting inside that async function, but not in the console.log at the bottom.
Anything outside of that async is going to continue on running as normal. So the console.log(getWeather(city, apiKey) keeps running even though that function has not gotten a response yet. There are a few solutions. First, you could await getWeather, which requires wrapping it in a function.
await function secondFunc(){
console.log(await getWeather(city, apiKey));
}
secondFunc();
In my opinion, the better way is to use .then. I almost always use it, it is cleaner and more logical to me. Don't forget that you can chain promise statements.
fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}`)
.then(response => response.json())
.then((response)=>{
console.log(response);
//Other code to do stuff with the response
})
.catch((error)=>{
console.log(error);
});
Another way to think of it is that the getWeather is Async, which will wait for a response, and return a promise in the meanwhile. But console.log is not async. So console.log keeps running as usual, but it has only recieved a Promise from getWeather, because that function is not resolved.
Hope that is clear. If you don't quite understand, let me know and I will do my best to explain further.
async functions return promises and since console.log isn't an async function it won't wait for getWeather() to resolve and will just log pending
hope that clears it up
id recommend just using .then()
//you could do
getWeather(city,ApiKey).then((response) =>{console.log(response));
hope that was helpful

javascript get Json data with fetch

I'm pretty noob in js. What I want to do is to send a get request to my server and receive a json. I can do this by fetch however, it returns a promise which is not suitable for me since I need to pass the received json to another function. Is there any way to get rid of promise? if not any alternative solution? I searched a lot but found no proper solution.
here's my function:
function fetchAndConvertData(path) {
return fetch(path).then(response =>
response.json().then(data => ({
data: data,
status: response.status
})
).then(async res => {
return res.data
}));
}
You can simply write :
async function fetchAndConvertData(path) {
const response = await fetch(path);
const data = await response.json();
return { // This is a Promise because async functions always return a Promise
data,
status: response.status
}
}
(async () => {
const result = await fetchAndConvertData("some/path/here");
console.log(result)
})();

How do I pass a parameter to API request 2, which I receive from API response 1 in react

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

Await Async call in javascript doesn't console.log in Node js

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();

Categories