javascript how to initialized a async await function into a variable - javascript

i am a beginner in javascript async await function. I have tried to make a asynchronous request in my backend and i want it to initialized in my variable but when I tried to log my variable, it gives me a promise and not a value. When i also tried to put an await. It gives me error.
Here is what I've done:
const getActivityContestApi = async () => {
try {
const response = await fetch(
`${getDjangoApiHost()}/api/events/event_activity_contests/`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
});
const data = await response.json();
return data;
} catch(error) {
console.log(error)
}
}
The function above is my asynchronous function, I want this to be stored in a variable like this:
const test_variable = getActivityContestApi();
console.log(test_variable);
this code gives me a promise. I want the actual variable so I tried to put await like this:
const test_variable = await getActivityContestApi();
console.log(test_variable);
this gives me error in react. please help.

await is only allowed inside async function.
const test_variable = await getActivityContestApi();
you can only use this statement inside another async function.

asyncFunction will return a promise. So if you just want get result, maybe you can use then
getActivityContestApi().then((resolve,reject)=>{
let test_variable = resolve;
console.log(test_variable);
})

await can't exist outside of async function. Here is what you need to do:
;(async () => {
const test_variable = await getActivityContestApi();
console.log(test_veriable);
})()

Related

pending promise inside async/await

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.

async await and promise chain is not waiting to resolve

I'm putting my API calls in a new function so I can easily call them with a couple of lines instead of a ton of code on every page. The problem I'm having is that the async and await is completing before returning the data.
I'm getting console.log(sess.getIdToken().getJwtToken()) consoled first, followed by undefined for console.log(getMessages), then the data from console.log(response).
So the await Auth.currentSession().then(...) runs but does't wait for the axios call inside of it. How do I return the data so I can access it in the useEffect?
useEffect(() => {
async function getMessages() {
const getMessages = await ApiService.getMessages();
console.log(getMessages)
}
getMessages();
}, []);
async getMessages() {
return await this.__sendRequest("/default/message", "GET");
}
async __sendRequest(url, method) {
await Auth.currentSession().then(sess => {
console.log(sess.getIdToken().getJwtToken())
axios({
method: method,
url: process.env.REACT_APP_USER_URL + url,
headers: {
"X-TOKEN-ID": sess.getIdToken().getJwtToken(),
"addresseeType": "P",
"content-type": "application/json"
}
}).then(function (response) {
console.log(response)
return response
}).catch(err => {
console.error(err);
})
})
}
Mixing async/await with promise-chaining (.then(...)) is a really easy way how to overcomplicate your code.
I can see a couple of places that contribute to this not working.
In __sendRequest you are not returning anything.
in the first .then you are lacking a return too.
Here is a simplified and fixed code
async __sendRequest(url, method) {
const sess = await Auth.currentSession()
console.log(sess.getIdToken().getJwtToken())
const response = await axios({
method: method,
url: process.env.REACT_APP_USER_URL + url,
headers: {
"X-TOKEN-ID": sess.getIdToken().getJwtToken(),
"addresseeType": "P",
"content-type": "application/json"
}
})
console.log(response)
return response
}
Check the comments of the other answer, to understand about async/await, returning and call stack https://stackoverflow.com/a/69179763/1728166
There are a couple of issues:
__sendRequest has no return, so when it's done waiting it will fulfill its promise with undefined.
The promise from the chain on Auth.currentSession() isn't waiting for the axios call to completely because the two chains aren't linked in any way.
(Not the reason you're seeing the premature settlement, but still an issue.) Don't trap errors too early, let them propagate so the caller knows that something went wrong.
Also, in general, don't mix using .then/.catch with async/await, there's no need (generally); just use await:
useEffect(() => {
async function getMessages() {
try {
const getMessages = await ApiService.getMessages();
console.log(getMessages);
} catch (error) {
// ...*** handle/report error...
}
}
getMessages();
}, []);
async getMessages() {
return await this.__sendRequest("/default/message", "GET");
}
async __sendRequest(url, method) {
const sess = await Auth.currentSession();
console.log(sess.getIdToken().getJwtToken());
return await axios({
method: method,
url: process.env.REACT_APP_USER_URL + url,
headers: {
"X-TOKEN-ID": sess.getIdToken().getJwtToken(),
"addresseeType": "P",
"content-type": "application/json"
}
});
}
getMessages() is async so you need to call with await
and make the callback function of first line async so you can use await inside it.
useEffect(async () => {
async function getMessages() {
const getMessages = await ApiService.getMessages();
console.log(getMessages)
}
await getMessages();
}, []);
you can simplify the __sendRequest by converting all then() callbacks into await and put the whole chain inside a try/catch block.

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

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

How to return data with Axios

I am trying to extract data from an Axios call in Javascript. I can see that the data is being called successfully if I console.log() while inside of this block
Here is a link to a screenshot of console.log() if it is inside the axios call. https://imgur.com/a/ZLXnE2n
This data is correct, but I can't access it outside of the axios call.
const response = await axios
.get(url, config)
.then(function(response) {
data = response.data;
console.log(data)
})
However, I am unable to do anything with the data outside of the getRide_Uber function. How do I extract the response object to use in other parts of my code?
const axios = require("axios");
// Use the Uber API to estimate the cost between two
// locations specified via latitude and longitude coordinates.
getRide_Uber = async (addressOrigin, addressDestination) => {
let origin = await geocodeAddress(addressOrigin);
let destination = await geocodeAddress(addressDestination);
const url = "https://api.uber.com/v1.2/estimates/price";
const config = {
headers: {
Authorization: `Token ${process.env.UBER_SERVER_TOKEN}`
},
params: {
start_latitude: origin.lat,
start_longitude: origin.lon,
end_latitude: destination.lat,
end_longitude: destination.lon
}
};
const response = await axios
.get(url, config)
.then(function(response) {
data = response.data;
return data;
})
.catch(function(error) {
console.log(error);
});
return response;
};
// Initial code
// const rideData = getRide_Uber("Arlington Texas", "Fort Worth Texas");
// const ridePrices = rideData.prices;
// console.log(ridePrices);
// Code suggestion by #mralanlee
const a = (async() => {
const result = await getRide_Uber(start, dest);
return result;
})();
console.log(a); // Console just says <pending>
const prices = a.prices // undefined
Please let me know if anything needs clarification and I will be happy to explain. Thanks!
The data store is back into getRide_Uber.
You can have it accessible or returned globally like:
(async() => {
const result = await getRide_Uber(start, dest);
// or console.log(result)
return result;
})()
or
const a = (async() => {
const result = await getRide_Uber(start, dest);
return result;
})();
For the above solution, you would need to have this in a scape of another async function. This will not work at the global level because logging the result will not wait for the Promise to resolve. You must wrap it into an async function and await the anonymous function.
Edit: Clarification to add more clarity...
To use the 2nd solution, you could do the following:
// this async function wraps around your code, we'll call it something for a lack of a better name
// start and dest params are passed into getRide_Uber
async function something(start, dest) {
const result = await getRide_Uber(start, dest);
// You can make sure you have the resolved data here.
// console.log(result.prices)
return result;
};
// now call the function
something(start, dest);

Categories