Last active
August 29, 2015 14:12
-
-
Save mixmix/b9573a0bfceea972aeca to your computer and use it in GitHub Desktop.
refacrotring callbacks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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']) | |
}) | |
} | |
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
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 byhttp.get
, but it's not given therecord
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 variablerecord
either.