In jQuery, the context is implicit, it's the one of window.document
.
When you use cheerio, you can have several contexts, but one per instance, and you bind this context using the load
function. There's no one global $
, but several ones if needed :
var $1 = cheerio.load(body);
var $2 = cheerio.load(someotherbody);
Your own code would have been less confusing if you hadn't forgotten the var
keyword. And yes you have a bug : if you're handling several requests in "parallel" they'll all have the same context (in fact it depends, you may have something worse than a bug : a potential bug that will unexpectedly arise later when adding some correct code).
Here's a typical code which probably looks like your own :
request(url, function(err, resp, body){
if (err) throw err;
$ = cheerio.load(body);
doSomethingAsynchronous(function callback(){
answer($, resp);
});
});
Here, the bug arise when doSomethingAsynchronous
doesn't complete before another request starts to be handled. In your case, there are a few reasons why you don't see any bugs :
- you don't use
$
after you made an asynchronous action and as there's only one user thread in node there can be no collision
doSomethingAsynchronous
is fast enough and thus is executed before another request starts to be answered
- everything happens so fast (remember : node is fast) that you never really have more than one request being handled
- you explicitly pass
$
as argument to doSomethingAsynchronous
, you don't refer to the global variable in the callback
But the bug will arise as soon as you enter the realm of "real applications" where you have many parallel requests and asynchronous actions.
Fix your code :
var cheerio = require('cheerio');
request(url, function(err, resp, body){
if (err) throw err;
var $ = cheerio.load(body);
// use $ here, you have one different instance per request, you may
// pass it, either explicitly as argument or using the closure
});