为什么cheerio $ variable不影响其他会话?

时间:2014-08-11 11:53:16

标签: javascript node.js cheerio

我在node.js上使用cheerio模块。 我知道在没有'var'关键字的函数中声明的变量是全局范围。

今天我认识到当cheerio将http body加载到$ variable时,变量不会使用keyward'var'。 我没有遇到任何问题。但突然间我感到困惑。 在我看来,变量$是全局范围,因此连接到服务器的所有会话必须共享相同的变量。

我认为我的javascript概念错了。请让我解决这个问题。

var cheerio = require('cheerio');

request(url, function(err, resp, body){
  if (err) throw err;
  $ = cheerio.load(body);
});

1 个答案:

答案 0 :(得分:2)

在jQuery中,上下文是隐式的,它是window.document的上下文。

当您使用cheerio时,您可以拥有多个上下文,但每个实例一个上下文,并使用load函数绑定此上下文。没有全球$,但如果需要,还有几个:

var $1 = cheerio.load(body);
var $2 = cheerio.load(someotherbody);

如果您没有忘记var关键字,那么您自己的代码就不那么容易混淆了。是的,你有一个错误:如果你在" parallel"中处理了几个请求。他们都有相同的上下文(实际上它取决于你,你可能会遇到比bug更糟糕的事情:一个潜在的错误,在添加一些正确的代码后会出乎意料地出现)。

这是一个典型的代码,可能看起来像你自己的代码:

request(url, function(err, resp, body){
  if (err) throw err;
  $ = cheerio.load(body);
  doSomethingAsynchronous(function callback(){
      answer($, resp);
  });
});

这里,当doSomethingAsynchronous在另一个请求开始处理之前没有完成时会出现错误。在你的案例中,有几个原因导致您没有看到任何错误:

  • 在您进行异步操作后不要使用$因为节点中只有一个用户线程没有冲突
  • doSomethingAsynchronous足够快,因此在另一个请求开始被回答之前执行
  • 一切都发生得如此之快(记住:节点很快)你从来没有真正有多个请求被处理
  • 您明确将$作为参数传递给doSomethingAsynchronous,您不会在回调中引用全局变量

但是当你进入"真实应用程序"的领域时,就会出现这个错误。你有很多并行请求和异步操作的地方。

修复您的代码:

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
});