我正在编写下面的代码,一次解析一个站点API,而不是告诉事件队列它已准备好下一个要解析的对象。我有问题,因为我还是新的javascript范围,并希望从SiteParser发出或调用emitForNext函数。我似乎无法将emitForNext带入错误回调的范围。
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);
});
};
}
答案 0 :(得分:4)
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()
大多数时候我们在函数的开头定义变量,因为函数体中定义的变量会被提升。基本上,它意味着它在整个函数中都可用,甚至在它被定义之前,但在这种情况下,它的值是undefined
。
例如,如果未定义变量,我们通常会获得ReferenceError
,但在下面的代码段中,console.log()
只打印undefined
。
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);
});
};
答案 1 :(得分:2)
为了能够访问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
的正文中。
答案 2 :(得分:1)
您需要在SiteParser本地范围内存储指向“this”对象的链接。
function SiteParser () {
var that = this; // store link to 'this' in local scope
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');
that.emitForNext();
} else {
processJSON(obJSON); //call the callback function
}
}) ;
}).on('error', function (e) {
that.emitForNext("got error: " + e.message);
});
};
}