0

I am reading JSON file using fs.readFileSync and for each document obtained, I am making a rest API call using client.post. Once I get response, I want to place the received content into another JSON file which is a replica of input JSON except additional element which is the data received from client.post call. However probably because of async nature of client.post, I am unable to add element to output JSON. I am new to NodeJS. Can you please help me where I am missing. Below is code and data

data:

[
    {
        "ticker": "CLYD"
    },
    {
        "ticker": "EGH"
    } 
]

Code:

var fs = require('fs');
var Client = require('node-rest-client').Client;

var data = fs.readFileSync(__dirname + "/data/stocks.json", "utf8");  
processData(data);

function processData (data) {

    var obj = JSON.parse(data);

    for (j = 0; j < obj.length; j++) {

        obj[j].stockInformation = getValuesForTicker (obj[j].ticker.trim());

    }

    var jsonOutput = JSON.stringify(obj,null,'\t');
    fs.writeFileSync(__dirname + "/data/response.json", jsonOutput);

};

function getValuesForTicker (ticker) {

    /**
     * More details and samples at https://www.npmjs.com/package/node-rest-client
     */
    var client = new Client();
    var values;

    // set content-type header and data as json in args parameter
    var args = {
        data: { "ticker" : ticker},
        headers: { "Content-Type": "application/json", "Accept" : "application/json" }
    };

    var responseToRequest = client.post("https://url.providing.response.as.json.content/", args, function (data, response) {
//         parsed response body as js object
        values = JSON.parse(JSON.stringify(data)).price;
    });
    return values;

};
JMD
  • 337
  • 4
  • 16

1 Answers1

0

Since getValueForTicker makes a async call to fetch data it should call a callback once data is recieved (or better a promise) and not return the result (currently undefined is returned as the value is returned before the value is assigned)

function getValuesForTicker (ticker, callback) {

    /**
     * More details and samples at https://www.npmjs.com/package/node-rest-client
     */
    return new Promise(function(resolve, reject) {

             var client = new Client();
             var values;

           // set content-type header and data as json in args parameter
            var args = {
              data: { "ticker" : ticker},
              headers: { "Content-Type": "application/json", "Accept" : "application/json" }
           };

          var responseToRequest = 
          client.post("https://url.providing.response.as.json.content/", args, function (data, response) {
         //         parsed response body as js object
             values = JSON.parse(JSON.stringify(data)).price;
             resolve(values)
        });

    };
})

and to get the data once async call is done you will need to call then function as below:

        getValuesForTicker(obj[j].ticker.trim())
        .then(function(val) {
             obj[j].stockInformation = val
        })

Considering you are new to node.js it will be hard to get.Take some time to understand callback and promise first.

Minkesh Jain
  • 1,140
  • 1
  • 10
  • 24
  • Thank you Minkesh. I tried the code you gave but couldn't use `obj[j].stockInformation = val` part of the code. I think that for an Async call, obj[j] goes out of scope. I am trying to figure out a way where I can set return values back to obj[j] – JMD Sep 26 '17 at 02:45
  • Actually, the for loop does not wait for the promise to resolve(or in another word, async call to complete). You can use `async` library to get the desired results. https://github.com/caolan/async .More specifically you will have to use `async.each` method. You can also achieve it by using `Promise.all`. – Minkesh Jain Sep 26 '17 at 06:15