1

I am trying to get "msg" out of this function to do math on it and it keeps coming back undefined. However when within the function I can read the data but cant do math on it.

let getArr = []
      const https = require('https')
        const options = {
          hostname: 'financialmodelingprep.com',
          port: 443,
          path: '/api/v3/quote/TSLA?apikey=?apikey=demo',
          method: 'GET'
        }
        
        const req = https.request(options, (res) => {
         
             res.on('data', (data) => {
             data = JSON.parse(data)
             data.map(( msg ) => {
                 //console.log(msg)
                 getArr.push(msg)
             })
          })        
        })  
     console.log(getArr.slice(-1)[0])     
  • From your code it seems like you are accessing the variable getArr before the API is returning the data You can also do you math after pushing the data to getArr variable i.e after data.map – Wamiq Rehman Jan 23 '21 at 23:31
  • I have a different function that I would like this data to head over to. To my understanding this is an async function. How do I make it patiently wait then update the global var? – Brandon Raeder Jan 23 '21 at 23:40
  • you can use await operator see this example https://stackoverflow.com/questions/8775262/synchronous-requests-in-node-js – Wamiq Rehman Jan 23 '21 at 23:45
  • You don't know when your callback `(res) => {` will execute, so setting a global variable doesn't help, since you won't know when to access that global variable as you won't know when it gets assigned data. If you want to pass the data to another function, call that function inside your `(res) => {` callback: `anotherFunc(data)`. Also, even though you don't need it, you shouldn't be using `.map()` here, use `.forEach()` when you don't want to return anything – Nick Parsons Jan 23 '21 at 23:48
  • @NickParsons Thank you – Brandon Raeder Jan 23 '21 at 23:55

2 Answers2

3

The code has two issues.

  1. Trying to access the results of processing the https request, the msg entries held in getArr, before the response from the request has been received:

    • data.map(( msg ) => {... is executed after the response is received in a call back function.
    • console.log(getArr.slice(-1)[0]) executes synchronously after issuing the request to the browser (which may or may not have initiated a network request yet) and certainly before the callback has been called.

    Canonical answer: How do I return the response from an asynchronous call?

  2. HTTP(S) responses are sent in packets and there is no guarantee that the first will contain all the JSON text there is to receive.

    • code must concatenate chunks of data passed to on("data", ) and only attempt to parse the full string in an on('end', ... ) callback handler.

    Previously answered to: SyntaxError: Unexpected end of JSON input at JSON.parse (... at IncomingMessage...

traktor
  • 17,588
  • 4
  • 32
  • 53
2

You are trying to access the variable before the async req function has returned.

Try:

let getArr = []
      const https = require('https')
        const options = {
          hostname: 'financialmodelingprep.com',
          port: 443,
          path: '/api/v3/quote/TSLA?apikey=?apikey=demo',
          method: 'GET'
        }
        
        const req = https.request(options, (res) => {
         
             res.on('data', (data) => {
             data = JSON.parse(data)
             data.map(( msg ) => {
                 //console.log(msg)
                 getArr.push(msg)
             })
             console.log(getArr.slice(-1)[0]);
          }) 
        })  
     //console.log(getArr.slice(-1)[0])     

How do I make it 'wait' and then update the global variable:

I see what you are saying, and what you may be confused about. Async programming in JS requires a bit of a paradigm shift. When you are writing async code, you don't want it to 'wait' and then update a global variable, you have to write the code INSIDE that async block. Having said that, you can write async code in more of a normal, 'wait' and 'update' fashion, but I suggest you start with brushing up on your async understanding. Here's a great link that I found helpful: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous

Jordan
  • 194
  • 1
  • 12
  • I appreciate it! Nick suggested just sending the data back up via a call back. You are also right but I dont want to write all my code in that block alone. I just need it for one piece of data. – Brandon Raeder Jan 24 '21 at 00:17