Events 如何从Node.js中的嵌套函数中向eventListener发出(javascript范围问题)

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

我正在编写下面的代码,它一次解析一个站点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);
            });
        };
    }

您需要在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);
    });
};

我选择这样做,结果它工作得很好,很抱歉花了一点时间来实现您的解决方案,我正忙于实现新功能!