Search code examples
javascriptnode.jsxmlhttprequest

HTTP Request in FOR loop is not executing


I have a script that is meant to execute a number of HTTP requests and then store the data retrieved:

var ParseXbrl = require('parse-xbrl')
var request = require('request');
var tickers = ['AAPL','F','TSLA','GOOG','MSFT'];

var json = "";
var XML = "";
var Data = [];

for(z in tickers){
request
.get('https://www.valuespreadsheet.com/iedgar/results.php?stock=' + tickers[z] + '&output=json')
.on('response', function(response) {
   response.on('data', function(chunk){
       json += chunk;
   });
   response.on('end',function(){
       json = JSON.parse(json);

       request
           .get(json.filings[2].instanceUrl)
           .on('response', function(response) {
               response.on('data', function(chunk){
                   XML  += chunk;
               });
               response.on('end',function() {
                   ParseXbrl.parseStr(XML).then(function(parsedDoc) {
                     console.log(parsedDoc);
                    var x = 0;
                       for(i in parsedDoc){
                            Data[tickers[z]][x]=parsedDoc[i];
                            x++
                            console.log(Data);
                       }
                   });
               });
               });
             });
   });
 }

The above script returns the following error code:

undefined:1
[object Object]{
 ^

SyntaxError: Unexpected token o in JSON at position 1
    at JSON.parse (<anonymous>)
    at IncomingMessage.<anonymous> (Test.js:18:24)
    at emitNone (events.js:110:20)
    at IncomingMessage.emit (events.js:207:7)
    at endReadableNT (_stream_readable.js:1047:12)
    at _combinedTickCallback (internal/process/next_tick.js:102:11)
    at process._tickCallback (internal/process/next_tick.js:161:9)
[Finished in 0.871s]

However when I change the array tickers such that it contains only one value e.g. tickers = ['AAPL'] the code works (what ticker I use is irrelevant).

I did some testing and noticed that when I added console.log(z); to my code it logged both 0 and 1 before it attempted to retrieve any data. This leads me to suspect that my code is looping through for(z in tickers) before it executes a request


Solution

  • The JSON string you are building is going to be invalid after the first request. If the API is returning an object, you are going to end up with:

    "{ response1: 'foo'}{ response2: 'bar}{ etc }"
    

    Which JSON.parse will error on, since it is not a single object (and that's what JSON.parse expects). If it's an array you have a similar problem:

    "[responseArray1][responseArray2]"
    

    Again, that will not parse because JSON.parse expects a single object. Brett is correct in his comment, you need to move where your json variable is defined:

    .on('response', function(response) {
       var json = "";
       response.on('data', function(chunk){
           json += chunk;
       });
    

    That way you won't be concatenating multiple request responses.

    The same also applies for XML = '';