I use cheerio module on node.js. And I've known that a variable declared in a function without 'var' keyword is global scope.
Today I recognized when cheerio loads http body into $ variable, the variable doesn't use the keyward 'var'. I'm not having any problem with it. But suddenly I got confused. In my opinion the variable $ is global scope so all session connects to server must share the same variable.
I think I have wrong concept with javascript. please let me fix this problem.
var cheerio = require('cheerio');
request(url, function(err, resp, body){
if (err) throw err;
$ = cheerio.load(body);
});
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 :
$
after you made an asynchronous action and as there's only one user thread in node there can be no collisiondoSomethingAsynchronous
is fast enough and thus is executed before another request starts to be answered$
as argument to doSomethingAsynchronous
, you don't refer to the global variable in the callbackBut 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
});