Events 如何从Node.js中的嵌套函数中向eventListener发出(javascript范围问题)
我正在编写下面的代码,它一次解析一个站点API,然后告诉事件队列它已准备好下一个要解析的对象。我遇到了一些问题,因为我还不熟悉javascript范围,希望从SiteParser发出或调用emitForNext函数。我似乎无法在错误回调中将emitForNext引入范围Events 如何从Node.js中的嵌套函数中向eventListener发出(javascript范围问题),events,node.js,scoping,Events,Node.js,Scoping,我正在编写下面的代码,它一次解析一个站点API,然后告诉事件队列它已准备好下一个要解析的对象。我遇到了一些问题,因为我还不熟悉javascript范围,希望从SiteParser发出或调用emitForNext函数。我似乎无法在错误回调中将emitForNext引入范围 function SiteParser(){ this.emitForNext = function (message) { this.emit("next", message);
function SiteParser(){
this.emitForNext = function (message) {
this.emit("next", message);
};
this.pullJSON = function (path, processJSON) { //processJSON is a callback function
var options = {
host: 'www.site.com',
port: 80,
path: path
}
//console.log("... processing "+path);
//pulls the entire json request via chunks
http.get(options, function (res) {
var resJSON = ''; //stores the comment JSON stream given in the res
res.on('data', function (chunk) {
resJSON+=chunk;
});
res.on('end', function () {
var obJSON = (JSON.parse(resJSON));
if (obJSON.hasOwnProperty("error")){
console.log(obJSON);
console.log('... ', path, ' does not exist');
//
//NEED A NEXT EVENT EMMITER HERE NEED TO FIGURE OUT SCOPE
//
//
} else {
processJSON(obJSON); //call the callback function
}
}) ;
}).on('error', function (e) {
emitForNext("got error: " + e.message);
});
};
}
您需要在SiteParser本地作用域中存储指向“this”对象的链接
函数SiteParser(){
var that=this;//在本地作用域中存储指向“this”的链接
this.emitForNext=函数(消息){
this.emit(“下一步”,消息);
};
this.pullJSON=function(path,processJSON){//processJSON是一个回调函数
变量选项={
主持人:“www.site.com”,
港口:80,
路径:路径
}
//console.log(“…处理”+路径);
//通过区块拉取整个json请求
get(选项、函数(res){
var resJSON='';//存储res中给定的注释JSON流
res.on('data',函数(块){
resJSON+=chunk;
});
res.on('end',function(){
var obJSON=(JSON.parse(resJSON));
if(obJSON.hasOwnProperty(“error”){
log(obJSON);
console.log(“…”,路径“不存在”);
那是一个;
}否则{
processJSON(obJSON);//调用回调函数
}
}) ;
}).on('error',函数(e){
emitForNext(“得到错误:+e.message”);
});
};
}
要访问emitForNext,您需要调用self.emitForNext
,其中self
指向您的SiteParser实例
像这样:
function SiteParser(){
this.emitForNext = function (message) {
this.emit("next", message);
};
this.pullJSON = function (path, processJSON) { //processJSON is a callback function
var options = {
host: 'www.site.com',
port: 80,
path: path
};
var self = this;
//console.log("... processing "+path);
//pulls the entire json request via chunks
http.get(options, function (res) {
var resJSON = ''; //stores the comment JSON stream given in the res
res.on('data', function (chunk) {
resJSON+=chunk;
});
res.on('end', function () {
var obJSON = (JSON.parse(resJSON));
if (obJSON.hasOwnProperty("error")){
console.log(obJSON);
console.log('... ', path, ' does not exist');
self.emitForNext(path + ' does not exist');
} else {
self.emitForNext('Successfully parsed the response');
processJSON(obJSON); //call the callback function
}
}) ;
}).on('error', function (e) {
self.emitForNext("got error: " + e.message);
});
};
}
但是,看起来您更愿意管理回调中的下一步操作(如解析下一个对象),即在
processJSON
的主体中,JavaScript具有函数作用域,如果您使用var关键字声明变量,它将是当前函数的局部变量。当您访问一个变量时,它将查看由当前函数、其父函数等组成的范围链…。尝试:
function one() {
var foo = 'foo';
function two() {
console.log(foo) // undefined. I'll explain this
var foo = 'bar';
console.log(foo) // bar
}
two()
console.log(foo) // foo
}
one()
大多数情况下,我们在函数的开头定义变量,因为函数体中定义的变量会被提升。基本上,这意味着它在整个函数中都是可用的,甚至在它被定义之前,但在这种情况下,它的值是未定义的
function foo() {
console.log(bar);
if (0) {
var bar = 'bar';
}
console.log(bar);
}
例如,如果一个变量没有定义,我们通常会得到一个ReferenceError
,但是在下面的代码段中,两个console.log()
只打印未定义的
function foo() {
console.log(bar);
if (0) {
var bar = 'bar';
}
console.log(bar);
}
所以,一种常见的做法是,当您编写长函数时,将其映射到self
function SiteParser() {
var self = this;
// ...
.error('error', function(err) {
self.emitForNext("got " + err.message);
})
}
你不应该把所有的方法都写在构造函数中,它只是在我们需要隐私的时候才有用,但是在这种情况下,你最好使用原型
把这些放在一起,我会写:
var SiteParser = function() {};
SiteParser.prototype.emitForNext = function(message) {
this.emit("next", message);
};
SiteParser.prototype.pullJSON = function(path, processJSON) {
var self = this,
options = {
host: 'www.site.com',
port: 80,
path: path
};
http.get(options, function(res) {
// ...
}).on('error', function (e) {
self.emitForNext("got error: " + e.message);
});
};
我选择这样做,结果它工作得很好,很抱歉花了一点时间来实现您的解决方案,我正忙于实现新功能!