2012-03-09 54 views
2

我正在编写下面的代码,一次解析一个站点API,而不是告诉事件队列它已准备好接下来要解析的对象。我遇到了问题,因为我仍然对JavaScript范围很陌生,并希望从SiteParser发出或调用emitForNext函数。我似乎无法将emitForNext带入错误回调的范围。如何从Node.js中的嵌套函数内发出eventListener(javascript范围问题)

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

回答

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

所以,一个普遍的做法是,当你编写长功能时,你将它映射到自我。

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

我选择了做这种方式,它结束了伟大的工作,对不起,它花了一些时间来实现您的解决方案,我正忙着落实新功能! – Hortinstein 2012-04-04 13:05:25

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); 
     }); 
    }; 
} 
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的身体。