0

I have a loop like this:

var req;

for (var i=0; i<sites.length; i++) {
    req = https.get(sites[i], handleRequest);
    req.on('error', handleError);
}

The callback (handleRequest) runs asynchronously, for each website being requested.

However, the only parameter in handleRequest seems to be a "response". When the callback is run, the loop has already completed, so how can I keep track of which website is this response for, so I can handle it accordingly?

Nuno
  • 3,082
  • 5
  • 38
  • 58
  • Does the response not say where it came from? I'm looking at [the documentation](https://nodejs.org/api/https.html) but it doesn't explain the response object. From the code samples, I can see that it has a `headers` property, so I'd expect it has the origin URL there. – VLAZ Oct 10 '19 at 16:55
  • Nope. Headers just show something like this: { "date": "Thu, 10 Oct 2019 16:30:08 GMT", "server": "Apache", "connection": "close", "transfer-encoding": "chunked", "content-type": "text/html; charset=UTF-8" } – Nuno Oct 10 '19 at 17:10
  • OK...weird. Anyway, I think I have a solution for you, then. – VLAZ Oct 10 '19 at 17:11
  • Bring it on!! :) thanks very much. – Nuno Oct 10 '19 at 17:34

1 Answers1

1

You can change your handleRequest to take two parameters - url being the first of them. With that you can partially apply the function via Function#bind and so set the url parameter at the time of calling but you'll still wait for the second argument.

let sites = [
  "https://example.com",
  "https://example.net",
  "https://example.org"
];

function handleRequest(url, res) {
  console.log("handling:", url);
  
  /* handling code */
}

//minimalistic dummy HTTP module that responds after 1 second
let https = {
  get: handler => setTimeout(handler, 1000)
}

for (var i=0; i < sites.length; i++) {
    let url = sites[i];
    https.get(handleRequest.bind(this, url)) //partially apply handleRequest
}

You can get a similar result via currying - instead of having two parameters, first take one, then return a function that takes the other. It leads to (in my opinion) better syntax when calling:

let sites = [
  "https://example.com",
  "https://example.net",
  "https://example.org"
];

function handleRequest(url) {
  return function actualHandler(res) {
    console.log("handling:", url);
  
    /* handling code */
  }
}

//minimalistic dummy HTTP module that responds after 1 second
let https = {
  get: handler => setTimeout(handler, 1000)
}

for (var i=0; i < sites.length; i++) {
    let url = sites[i];
    https.get(handleRequest(url))
}
VLAZ
  • 26,331
  • 9
  • 49
  • 67