3

I am writing an API wrapper in NodeJs, and am getting hung up on trying to cleanly handle the response from http.get(). The problem's root is that I hate the unclean coding style in all tutorials where the callback method is defined anonymously inline.

// Bad. Can get ugly if the handle function has multiple lines or nested callbacks
http.get("www.example.com", function(response){/* handle response */});

// Better. Follows clean-code guidelines. Code is more reusable. Etc
var handleResponse = function(response){
    // handle response
}
http.get("www.example.com", handleResponse);

While I like the latter so much more, I can't seem to pass extra parameters to handleResponse, specifically the callback that I want handleResponse to call.

What I have currently that works:

module.exports = function() {
    return {
        apiGet: function(url, callback) {
            http.get(url, function(response) {
                var result = handleResponse(response);
                callback(null, result);
            });
        }
    }
}

What I want to have (but doesn't work)

module.exports = function() {
    var handleResponse = function(response) {
        var result = handleResponse(response);
        callback(null, result);
    };

    return {
        apiGet: function(url, callback) {
            http.get(url, handleResponse);
        }
    }
}

The problem with this code is that callback is not defined in the method handleResponse(). I can't seem to get around this.

Things I've tried.

// hoping extra parameters get passed to function. Nope.
return {
    http.get(url, handleResponse, callback); 
}

// Trying out a suggestion from a random blog I found while googling for an answer. Nope.
return {
    http.get(url, handleResponse.bind({callback: callback}); 
}
user779860
  • 665
  • 1
  • 7
  • 15

3 Answers3

4

If you have a function who's main job is to do something then pass on the control flow to other functions then perhaps instead of writing a handleResponse() function you should consider writing a makeResponseHandler(). Basically, use a function factory:

function makeResponseHandler (callback) {
    return function (response) {
        // deal with response here
        callback(null, result);
    }
};

return {
    apiGet: function(url, callback) {
        http.get(url, makeResponseHandler(callback));
    }
}

Note: If you look carefully, you're not actually passing makeResponseHandler to http.get(), you're calling makeResponseHandler() and passing what it returns to http.get().

slebetman
  • 109,858
  • 19
  • 140
  • 171
1

So I found something that does work in this related thread.

return {
    http.get(url, function(response){ handleResponse(response, callback); }); 
}

That seems to be a reasonable compromise. I can turn a long anonymous function into a small anonymous function that simply calls my explicit function with the needed information.

Before I go with this, does anyone have any other suggestions for what I'm trying to accomplish? I'm always seeking the highest level of code readability.

user779860
  • 665
  • 1
  • 7
  • 15
0

Why not use:

var req = http.get("www.example.com");

req.SOME_VARIABLE = "something";

req.on("response", function(res){
    //Do something with req.SOME_VARIABLE
});