I'm a new to coding and currently struggling with promises and await/async. I'm trying to access the data coming from the currPrice
variable outside of the function scope. Can someone point me in the right direction?
var price
const getPrice = async () => {
//Get the curent market price
var marketSymobl = checkOrders[i].symbol.split(" - ")[0].toUpperCase()
console.log(checkOrders[i].symbol)
finnhubClient.quote(marketSymobl, (error, data, response) => {
const currPrice = data.c
console.log(currPrice);
return currPrice
});
}
//const x = getPrice().then(price => (console.log(x)))
price = await getPrice()
console.log(price);
CodePudding user response:
The problem here is that when you do return currPrice
you are returning from the callback in the quote
function, thus not getting the value in the scope of the getPrice
function. Because this is a callback, once it is executed the getPrice
function already left the event stack with undefined
as the return value. Check this video to learn about the event loop.
A way you could fix this would be to do something like:
const getPrice = async () => {
//Get the curent market price
const marketSymobl = checkOrders[i].symbol.split(" - ")[0].toUpperCase()
// We are wrapping this function in a promise so that we can await it
const quotePromise = new Promise((resolve, reject) => finnhubClient.quote(marketSymobl, (error, data, response) => {
if (error) {
// Rejecting with error so you have the freedom to handle it however you want
reject(error)
} else {
resolve(data.c)
}
});
const currPrice = await quotePromise();
return currPrice
}
This way you are returning from the getPrice
function.
Note: I changed your var
variables to let
. Have a look at this post for an explanation why
Edit 1: I changed your marketSymobl
variable to be const
, since you don't mutate it afterwards
Edit 2: Wrapped the quote function in a promise so it can be awaited
Edit 3: Edited initial statement and added reference to event loop video.
CodePudding user response:
Async/await
is just a syntactic sugar over promises. Promise can be returned as resolved or rejected and you use then/catch
block to get the result/error based on the promise status returned. I am attaching a link to go through and understand how they work and when they are needed.
Now, let's understand the code you wrote:
var price;
// async method automatically returns promise
const getPrice = async () => {
//Get the curent market price
var marketSymobl = checkOrders[i].symbol.split(" - ")[0].toUpperCase()
console.log(checkOrders[i].symbol);
// callback which is called when the async
// task is completed or failed with error, so using await we can
// make it await for this async task to complete first
// and then move to subsequent lines
// try to put await code under try/catch
try {
const currPrice = await finnhubClient.quote(marketSymobl) // if this return the promise
return currPrice.c
} catch(e) {
console.log(e);
}
}
// here x will never get the value returned from getPrice.
// to get the values form getPrice, you can use then operator
// on x like this
//const x = getPrice();
// x.then(price => (console.log(x))).catch((e) => console.log(e));
//const x = getPrice().then(price => (console.log(x)))
price = await getPrice(); // this will return the response or error based on promise value
console.log(price);
Note: finnhubClient.quote
if this method returns the promise the above code will work fine else it won't work. Also, I suggest you to check this link for async/await.
When finnhubClient.quote
is not promise based, you can return promise.
const getPrice = () => {
return new Promise((res, rej) => {
//Get the curent market price
var marketSymobl = checkOrders[i].symbol.split(" - ")[0].toUpperCase()
console.log(checkOrders[i].symbol)
finnhubClient.quote(marketSymobl, (error, data, response) => {
if (error) reject(error);
const currPrice = data.c
console.log(currPrice);
resolve(currPrice)
});
})
}