1

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

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

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

var cheerio = require('cheerio');

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

1 回答 1

2

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

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

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

如果您没有忘记var关键字,您自己的代码就不会那么混乱了。是的,您有一个错误:如果您“并行”处理多个请求,它们将具有相同的上下文(实际上取决于情况,您可能遇到比错误更糟糕的情况:一个潜在的错误,稍后会意外出现)添加一些正确的代码)。

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

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
});
于 2014-08-11T11:54:27.657 回答