1

I'm fairly new to Node and Javascript and I'm struggling with my first Node module. What I'm trying to do is export functions for specific API calls and I'd like to reuse my https.request function rather than duplicating the code in each function. For some reason I'm failing to wrap my head around how to pass the data back to my original function. Here's an abbreviated version - the listStuff function would be one of many to handle various api request actions.

'use strict';
const https = require('https');
const _ = require('underscore');
const hostStr = 'api.server.net';

function listStuff(){
  var pathStr = '/release/api/stuff';
  _apiCall(pathStr);
  //Would like to handle the https response data here
};

function _apiCall(pathStr){
  var options = {
    host: hostStr,
    path: pathStr
  };

  var req = https.get(options, function(res) {
    console.log("statusCode: ", res.statusCode);
    console.log("headers: ", res.headers);

    var responseString = '';

    res.on('data', function(d){
      responseString += d;
    });

    res.on('end', function(){
      var responseObject = JSON.parse(responseString);
    });
  });

  req.end();

  req.on('error', function(e){
    console.log(e);
  });
};

module.exports = {
  listStuff: listStuff
};
Jeremy R
  • 13
  • 3
  • Use a callback, or - more sophisticated - a promise. You [cannot directly `return` it](http://stackoverflow.com/q/14220321/1048572). – Bergi Oct 21 '15 at 02:47
  • Thanks Bergi - That's what I'd gathered from reading Node docs but it's breaking my brain a bit on how to accomplish it here. I'm sure it's just my inexperience showing through. . – Jeremy R Oct 21 '15 at 02:52
  • I had tried: _apiCall(pathStr, function(data, err){console.log(data)}; in my list stuff function but it broke down on me from there - I feel like I was on the right track but perhaps not. – Jeremy R Oct 21 '15 at 02:53
  • Yes you were on the right track. Now you need to make the `_apiCall` function accept such a function as an additional parameter (name it `callback`), and then call that function once you have the `responseObject`. – Bergi Oct 21 '15 at 02:56
  • Thanks Bergi - that has me on the right track - I'm at least getting an 'undefined' back in my callback function now - bit of hacking yet to sort that out - I'll update here if I get stuck again or add my solution. – Jeremy R Oct 21 '15 at 03:03
  • Thanks everyone for the help - Bergi got me 99% of the way there last night and Kinetics took it the rest of the way. Traktor53 - Thanks for the feedback on promises - I'm definitly going to take that and study up on it. – Jeremy R Oct 21 '15 at 20:04

2 Answers2

2

Hope this helps. Register a callback in the apiCall function, and then check the callback params for error handling. Then, just make sure you return the callback when you want to end the function call (either in the on end or on error processing).

       function listStuff(){
          var pathStr = '/release/api/stuff';
          _apiCall(pathStr, function(err, data) {
             if (err) // handle err
             //handle data.
           });
        };

        function _apiCall(pathStr, callback){
          var options = {
            host: hostStr,
            path: pathStr
          };

          var req = https.get(options, function(res) {
            console.log("statusCode: ", res.statusCode);
            console.log("headers: ", res.headers);

            var responseString = '';

            res.on('data', function(d){
              responseString += d;
            });

            res.on('end', function(){
              var responseObject = JSON.parse(responseString);
              return callback(null, responseObject);    
            });
          });

          req.end();

          req.on('error', function(e){
            console.log(e);
            return callback(e);
          });
        };
Olivercodes
  • 1,048
  • 5
  • 17
0

A slightly different approach using Promise objects. Note I looked into this as a learning exercise and hope it helps. I have not written all the code for you and the debugging is all yours!

Firstly make _apiCall returns a promise object.

function listStuff()
{
    var pathStr = '/release/api/stuff';
    var promise = _apiCall(pathStr);
    promise.then( function( responceObject){

     // handle response object data

    });

    promise.catch( function( error){
        console.log( error.message);  // report error
    });
}

Next step is to make _apiCall return a promise object for the HTTPS request it will initiate inside the executor of promise creation.

function _apiCall(pathStr)
{   var options = {
        host: hostStr,
        path: pathStr
    };

    function beginGet( worked, failed)
    {
        // see below
    }

    return new Promise( beginGet);
}

Lastly write beginGet to initiate and call back success or fail functions depending on the outcome of the get request.

function beginGet( worked, failed)
{   var req;
    var responseObj;

    function getCallBack( res)
    { // all your get request handling code
      // on error call failed( error)
      // on sucessful completion, call worked(responseObj)
    }
    req = https.get(options, getCallBack);
}

Also please check with https.get documentation - I think it calls req.end() for you. All the other errors are mine :-)

traktor
  • 17,588
  • 4
  • 32
  • 53