Async Function Promise (axios) - javascript

I am trying to fetch the gas prices from ethgasstaion and work with this value in the global scope. Is there a way that I can include a global variable in my .then() part and assign the value of my async function to that variable?
I get the right value but can't assign it to the global variable.
// Eth Gas Station
let fast_value = 0;
async function getCurrentGasPrices() {
let response = await axios.get(process.env.ETH_GAS_Station_API)
let price = {
fast: response.data.fast
}
return price
}
getCurrentGasPrices().then(value => {
fast_value += value.fast;
})
console.log(fast_value)
Appreciate the help!

You can wrap everything into an immediately invoked async function, so we can use await inside:
(async () => {
let fast_value = 0;
async function getCurrentGasPrices() {
let response = await axios.get(process.env.ETH_GAS_Station_API);
let price = {
fast: response.data,
};
return price;
}
let response = await getCurrentGasPrices();
fast_value = response.fast;
console.log(fast_value);
})();

Related

async/await logs to the console but returns no value and returns `Promise { pending }`

I have been trying to get the result of this asynchronous function to no degree of success for the past few hours. I have checked the past similar questions and solutions but nothing has worked for this specific case.
This particular code below logs the value when I run console.log:
const okay = async () => {
console.log(await getTimezoneLabel(timezone));
};
okay();
The code below logs Promise {pending} instead of a value to the console which is baffling
const okay = async () => {
return await getTimezoneLabel(timezone);
};
let result = okay();
console.log(result);
Here is the getTimezoneLabel function itself:
async function getTimezoneLabel(timezone) {
const timezoneObject = await convertTimezone('original', timezone);
return timezoneObject[0].label;
}
Here is the convertTimezone function which the getTimezoneLabel function references:
import timezonesList from '../timezone-list';
async function convertTimezone(labelStyle, timezone) {
const spacetime = (await import('spacetime')).default;
const soft = (await import('timezone-soft')).default;
const timezones = Object.fromEntries(Object.entries(timezonesList).filter(([key]) => key.includes(timezone)));
return Object.entries(timezones)
.reduce((selectOptions, zone) => {
const now = spacetime.now(zone[0]);
const tz = now.timezone();
const tzStrings = soft(zone[0]);
let label = '';
let abbr = now.isDST()
? // #ts-expect-error
tzStrings[0].daylight?.abbr
: // #ts-expect-error
tzStrings[0].standard?.abbr;
let altName = now.isDST() ? tzStrings[0].daylight?.name : tzStrings[0].standard?.name;
const min = tz.current.offset * 60;
const hr = `${(min / 60) ^ 0}:` + (min % 60 === 0 ? '00' : Math.abs(min % 60));
const prefix = `(GMT${hr.includes('-') ? hr : `+${hr}`}) ${zone[1]}`;
switch (labelStyle) {
case 'original':
label = prefix;
break;
case 'altName':
label = `${prefix} ${altName?.length ? `(${altName})` : ''}`;
break;
case 'abbrev':
label = `${prefix} ${abbr?.length < 5 ? `(${abbr})` : ''}`;
break;
default:
label = `${prefix}`;
}
selectOptions.push({
value: tz.name,
label: label,
offset: tz.current.offset,
abbrev: abbr,
altName: altName,
});
return selectOptions;
}, [])
.sort((a, b) => a.offset - b.offset);
}
How can I get this to work?
Thank you so much in advance.
I'm simplifying quite a lot here, but it helps to understand. When you declare a function as async, what it does is wrap the function in a Promise. So, for example, this function :
async function something(){ return "hello world" }
can be read like :
function something(){
return new Promise((resolve, reject) => {
resolve("hello world")
})
}
In a nutshell, a Promise just schedules the execution of a function (in this case something) for later. So, we can only read the returned value later, when it's ready. When you call something(), it returns a Promise which is pending because it hasn't been executed yet (its execution is put on hold in a queue). You can learn more about how this works by reading about the event loop, the call stack and event queue.
To get the returned value of a Promise, we use a method called .then((value) => {}) which returns in the variable value the returned value of the function (in our case, value will contain "hello world"). So :
let r = something()
console.log(r) // Promise pending
r.then((value) => {
console.log(value) // "hello world"
})
If you want to use the value, you are gonna have to either :
Put your code inside the .then() and continue there
Put your code inside an async function and use await in front of the call
async function run(){
let value = await something()
console.log(value) // "hello world"
// do things with value
}
run()
This is a similar question that is already answered with some good explanation
Well basically async function returns a promise.
You can use use let somevariable = await okay() inside an async function
OR
You could do it like
okay().then((resp)=>{
console.log(resp)
})
An async function return a promise. Try that:
const okay = async () => {
return await getTimezoneLabel(timezone);
};
okay().then(result=>console.log(result));
or if you call okay() inside another async function you may use await syntax:
// should be inside async function
const result = await okay();

How can I access and use a return value from a do while loop?

I am trying to access return data from a do while loop, but I am unable to do so.
I have stored the information in a new variable (starships) and then returned this variable, but it says starships is not defined. I see that this may be a scoping issue, how can I resolve this?
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
let starships = allResults;
return starships;
}
console.log(starships);
You need to get the value which is returned from getData. The most obvious way to do this with the async/await structure you have is to just await it:
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
let starships = allResults;
return starships;
}
async function doTheDo() {
const test = await getData();
console.dir(test);
}
doTheDo();
you can do this. starships is defined inside the loop. Additionally, you are not calling getData() function. You can store that return value like this
const result = await getData();
console.log(result);
or you can directly print like this. console.log(await getData())
async function getData() {
const allResults = [];
let url = 'https://swapi.co/api/starships/';
do {
const res = await fetch(url);
const data = await res.json();
url = data.next;
allResults.push(...data.results);
console.log(allResults);
} while (url !== null)
return allResults;
}
console.log(await getData());
Async functions return a promise, which means you have to access the return value with a .then().
However, you have another problem: starships is in the scope of the function getData() which you have defined, but not called.
So first lets call your function:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
console.log(getData());
Now you will see that your log value is [object Promise] which isn't so helpful in its current form. This is because the code outside the async function is running synchronously, which means we don't have the value yet, just a promise to maybe return the value sometime in the future.
So now we need to access the promise asynchronously using the .then() like so:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
getData().then(starships => {
console.log(starships);
});
Now you should see the info you were expecting to be logged.
You can also save promise to a variable and pass it around and access it elsewhere in your code like so:
async function getData() {
const allResults = [];
// do stuff
let starships = allResults;
return starships;
}
let starshipPromise = getData();
// time & code passes...
starshipPromise.then(starship => {
console.log(starship);
}).catch(error => {
// handle error
});
And don't forget to catch your rejected promises!
See the MDN docs on Async functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
And if you need more info on promises, go here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

promises scope using await and async

var accountA;
var accountB;
accounts = async () => {
accountA = await server.loadAccount(Apub)
console.log(accountA)
accountB = await (server.loadAccount(Bpub))
}
accounts()
console.log(accountA);
1) Apub is my public key which i have already declared
2)when i am printing the
accountA
inside the function it is showing me complete details from accountA
3) when i do console.log outside the function, the output is
undefined
4) i have declared the variables outside the function as the global scope
please help me
Although you are using await inside the function you are not waiting till it you get a response while you call accounts which is an async function
var accountA;
var accountB;
accounts = async () => {
accountA = await server.loadAccount(Apub)
console.log(accountA)
accountB = await (server.loadAccount(Bpub))
}
accounts().then(() => {
console.log(accountA);
})
If you have the above code in a function which is async then you could use await with accounts too
await accounts()
Your accounts function is asyncronous. So the console.log() in the last line is called first, before accounts has time to finish. This is why it displays undefined. You have to wait for accounts to finish before printing it by adding an "await" before your call.
var accountA;
var accountB;
accounts = async () => {
accountA = await server.loadAccount(Apub)
console.log(accountA)
accountB = await (server.loadAccount(Bpub))
}
await accounts()
console.log(accountA);

Use information from a promise programatically

I made a small webpage that takes information from the "Yahoo Weather" API and displays it in divs on the page.
This is the JS:
const url = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
let data = 1;
const getWeather = async function() {
const fetchWeather = await fetch(url);
const result = await fetchWeather.json();
return data=result;
}
getWeather();
const showData = async function(info) {
let html = '';
const newInfo = info.query.results.channel.item.forecast.map((item, index) => {
html += `<div id='item${index}'><p>Date: ${item.date}</p>`;
html += `<p>Day: ${item.day}</p>`;
html += `<p>Highest temp: ${item.high}</p>`;
html += `<p>Lowest temp: ${item.low}</p></div>`;
return html;
});
}
const display = async function() {
const info = await showData(data);
weatherInfo.innerHTML = data;
}
display();
My goal is that when the page loads, it displays the information gathered from the promise returned by the API.
I get this error:Uncaught (in promise) TypeError: Cannot read property 'results' of undefined
Basically as far as I understand, by the time the "display()" is invoked, the variable "data" doesn't have anything in it yet.
What I'm trying to achieve is that display() will only work after "data" is defined, but without a for loop or something like that.
Any help will be appreciated!
As far as I understand, by the time the "display()" is invoked, the variable "data" doesn't have anything in it yet.
Yes. Don't use a global data variable at all1. getWeather returns a promise that will fulfill with the data, so you know exactly when it becomes available:
getWeather().then(display);
with
async function getWeather () {
const fetchWeather = await fetch(url);
const result = await fetchWeather.json();
return result; // drop the `data =` assignment
}
async function display(data) {
// ^^^^
const info = await showData(data);
weatherInfo.innerHTML = info;
}
Alternatively, especially when you don't want to use a then chain, just put const data = await getWeather(); in the display function.
1: If you insist to store the data in the global scope because you want to use it in multiple places, put the promise for the data in the variable not the result itself.
Here is my solutiuon:
const url = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22nome%2C%20ak%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
const getWeather = async function() {
const fetchWeather = await fetch(url);
return await fetchWeather.json();
}
const showData = async function(info) {
let html = '';
info.query.results.channel.item.forecast.map((item, index) => {
html += `<div id='item${index}'><p>Date: ${item.date}</p>`;
html += `<p>Day: ${item.day}</p>`;
html += `<p>Highest temp: ${item.high}</p>`;
html += `<p>Lowest temp: ${item.low}</p></div>`;
});
return html;
}
const display = async function() {
const data = await getWeather();
const info = await showData(data);
weatherInfo.innerHTML = info;
}
display();
https://plnkr.co/edit/1b0fpBji7y6sZPODPDjY?p=preview

Unable to receive proper data from the promise function

I am trying to scrap wikipedia page to fetch list of airlines by first scrapping first page and then going to each individual page of airline to get the website url. I have divided the code in two functions. One to scrap main page and get a new url, and second function to scrap another page from the created url to get the website name from that page. I have used request-promise module for getting the html and then cheerio to parse the data.
export async function getAirlinesWebsites(req,res) {
let response = await request(options_mainpage);
console.log(`Data`);
let $ = cheerio.load(response);
console.log('Response got');
$('tr').each((i,e)=>{
let children = '';
console.log('inside function ', i);
if($(e).children('td').children('a').attr('class') !== 'new') {
children = $(e).children('td').children('a').attr('href');
let wiki_url = 'https://en.wikipedia.org' + children;
console.log(`wiki_url = ${wiki_url}`);
let airline_url = getAirlineUrl(wiki_url);
console.log(`airline_url = ${airline_url}`);
}
})
And then the getAirlineUrl() function will parse another page based on the provided url.
async function getAirlineUrl(url){
const wiki_child_options = {
url : url,
headers : headers
}
let child_response = await request(wiki_child_options);
let $ = cheerio.load(child_response);
let answer = $('.infobox.vcard').children('tbody').children('tr').children('td').children('span.url').text();
return answer;
})
However when I console log the answer variable in the parent function, I get a [object Promise] value instead of a String. How do I resolve this issue?
Async function return promise.In case of that,you need to use then to get resolved response or use await.
This should work if other part of your code is ok.
export async function getAirlinesWebsites(req, res) {
let response = await request(options_mainpage);
console.log(`Data`);
let $ = cheerio.load(response);
console.log("Response got");
$("tr").each(async (i, e) => {
let children = "";
console.log("inside function ", i);
if ($(e).children("td").children("a").attr("class") !== "new") {
children = $(e).children("td").children("a").attr("href");
let wiki_url = "https://en.wikipedia.org" + children;
console.log(`wiki_url = ${wiki_url}`);
let airline_url = await getAirlineUrl(wiki_url);
console.log(`airline_url = ${airline_url}`);
}
});
}
Since your getAirlineUrl function returns a promise, you need to await that promise. You can't have await nested inside of the .each callback because the callback is not an async function, and if it was it wouldn't work still. The best fix is the avoid using .each and just use a loop.
export async function getAirlinesWebsites(req,res) {
let response = await request(options_mainpage);
console.log(`Data`);
let $ = cheerio.load(response);
console.log('Response got');
for (const [i, e] of Array.from($('tr')).entries()) {
let children = '';
console.log('inside function ', i);
if($(e).children('td').children('a').attr('class') !== 'new') {
children = $(e).children('td').children('a').attr('href');
let wiki_url = 'https://en.wikipedia.org' + children;
console.log(`wiki_url = ${wiki_url}`);
let airline_url = await getAirlineUrl(wiki_url);
console.log(`airline_url = ${airline_url}`);
}
}
}

Categories

Resources