Skip to content

Instantly share code, notes, and snippets.

@mixmix
Last active August 29, 2015 14:12
Show Gist options
  • Save mixmix/b9573a0bfceea972aeca to your computer and use it in GitHub Desktop.
Save mixmix/b9573a0bfceea972aeca to your computer and use it in GitHub Desktop.
refacrotring callbacks
var http = require('http')
var completeCount = 0
var dataStore = []
for (var i=0; i<(process.argv.length-2); i++) {
dataStore[i] = {
url: process.argv[i+2],
response: ''
}
}
dataStore.forEach( function(record) {
http.get(record['url'], function(response) {
response.setEncoding('utf8')
response.on('error', console.error)
response.on('data', function store(data) {
record['response']+= data
})
response.on('end', function() {
completeCount++
if (isLastFinished()) {
printResponses()
}
})
})
})
/***** **Attempted refactor** ********
dataStore.forEach( function(record) {
http.get(record['url'], processResponse);
})
var processResponse = function(response) {
response.setEncoding('utf8')
response.on('error', console.error)
response.on('data', store)
response.on('end', function() {
completeCount++
if (isLastFinished()) {
printResponses()
}
})
}
var store = function(data) {
console.log('.')
record['response']+= data
}
*/
var isLastFinished = function() {
return (completeCount === dataStore.length)
}
var printResponses = function() {
dataStore.forEach( function(record) {
console.log(record['response'])
})
}
@mixmix
Copy link
Author

mixmix commented Dec 31, 2014

what this does

the above code allows you to run command node this_code.js url1 url2 ...

It does n asynchronous GET requests, then when it's finished receiving all of them, it prints the responses in the same order as they were asked for (url1, url2 ... ).

analysis

What I don't like about this js so far is that it's getting super nested and terse super quickly.
My instinct is to extract the seperate concerns into discrete methods like printResponses.
However I don't know how to do this yet with parts of this code.

specific examples

commented out is my attempted refactoring (lines 32-58) which breaks the code.

I think the problem I'm facing is trying to combine the idea of (async) callback methods + variables across callback scope? (I'm right on the edge of what I can communicate clearly I'm afraid).

[e.g. 1] when processResponse is called as a callback on line 35, it gets given a response variable by http.get, but it's not given the record variable ?

[e.g. 2] I think there's a similar problem with the callback (or dependency injection) on line 43, where the store method probably doesn't know about the variable record either.

@ahdinosaur
Copy link

a common pattern you're missing here is creating a function that takes in arguments and returns a second function with the arguments as variables for the second function.

for example, we can make a function that takes in a single number argument x and returns x + 10.

var addTen = function (x) {
  return x + 10;
};

addTen(100); // 110

or we can create a function that takes in a single number argument n and returns a function that takes in a single number argument x and returns x + n.

var addN = function (n) {
  return function (x) {
    return x + n;
  };
};

var addTen = addN(10);

addTen(100); // 110

we call this pattern a closure.

both processResponse and store require access to record, so they should be wrapped in a function that takes them as an argument.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment