Home > other >  Not able to access the variable outside of a request
Not able to access the variable outside of a request

Time:11-12

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