Retrieving the lotto numbers - Node.js I'm looking for feedback as to how I've structured the async calls, and If anything should be written differently.

endpoints.js

module.exports = {
  lotto: 'https://www.norsk-tipping.no/api-lotto/getResultInfo.json?drawID=',
  keno: 'https://www.norsk-tipping.no/api-keno/getResultInfo.json?drawID=',
  extra: 'https://www.norsk-tipping.no/api-extra/getResultInfo.json?drawID=',
  vikinglotto: 'https://www.norsk-tipping.no/api-vikinglotto/getResultInfo.json?drawID=',
  joker: 'https://www.norsk-tipping.no/api-joker/getResultInfo.json?drawID=',
  eurojackpot: 'https://www.norsk-tipping.no/api-eurojackpot/getResultInfo.json?drawID='
};


service.js

var request      = require('request');
var gametypes    = require('./endpoints');

function toJSON(response){
    var data    = response.toString(),
        result  = data.match(/(^{[\s\w\W]+}$)/gm).join('');

    return JSON.parse(result);
}


function getResults(opts, callback){
    var url                     = gametypes[opts.type],    
        fromDrawID              = opts.fromDrawID,
        toDrawID                = opts.toDrawID,
        numberOfRequestsWanted  = toDrawID - fromDrawID,
        numberOfRequestsDone    = 0,
        data                    = [];

    //If either the object is missing or
    //the object with no key of 'type' is passed in - return error. 

    if(!opts.type){
        return callback(new Error('Missing required param: Object with key: type'), null);
    }


    if(fromDrawID &amp;&amp; toDrawID) {
        console.log('Fetching the requested results from https://www.norsk-tipping.no...');

        while(fromDrawID &lt;= toDrawID) {
            doRequest(url + fromDrawID++, callback);
        }
    } else {
        console.log('Fetching the latest result from https://www.norsk-tipping.no...');
        doRequest(url, callback);
    }

    function doRequest(url, callback) {

        request(url, function(error, response, body) {
            if(!error &amp;&amp; response.statusCode === 200) {
                data.push(toJSON(body));

                if(numberOfRequestsDone++ === numberOfRequestsWanted) {
                    return callback(null, data);
                } 

            } else {
                return callback(error, null);
            }
        });
    }
}

module.exports = getResults;


example usage

var lotto    = require('./service');
var options  = { type: 'vikinglotto', fromDrawID: 1, toDrawID: 500};


lotto(options, function(err, results) {
    if (err) console.log(err);

    else {        
        console.log(data);
    }
});
Suggesting you move to using promises instead of callbacks. This way, you don't have to do the tango with calling callbacks, collecting results and all. You can simply replace the request module with the request-promise module.

function getResult(options){
  ...
  return doRequest(options);
}

...

lotto(options).then(results =&gt; console.log(data), err =&gt; console.log(err));


There's little merit of putting doRequest inside getResults. It's only being used in getResults but it's not exposed anyways. Suggesting you move it out into the module.

JavaScript doesn't have default argument values (yet) but you can easily do the same thing using Object.assign. Provide a default object, and merge to a new object the defaults and the one from the arguments. This way, you avoid having to do a lot of default logic and value checks.

var defaults = {...}

function getResults(options){
  var mergedOptions = Object.assign({}, defaults, options);
  ...
}


Back to promises, firing multiple async calls in parallel using callbacks will require you to collect results and keep checking if all the requests have responded. When using Promises, you can easily use Promise.all to listen to an array of promises.

var request = require('request-promise');

function getResult(options){
  ...
  var drawRange = toDrawID - fromDrawID;

  // Create an array of drawIds and map them to promises
  var promises = Array(drawRange).fill(fromDrawID).map((fromDrawID, i) =&gt; {
    return request(url + (fromDrawID + i));
  });

  return Promise.all(promises);
}