nic*_*ten 3 events event-handling javascript-events node.js coffeescript
我在CoffeeScript/NodeJS中看到一些关于EventEmitters和处理程序的非常奇怪的行为.我把一个展示问题的小样本放在一起......
基本上我在事件处理方面有一些间接性,但除非我将第一个事件处理程序包装在lambda中,否则我似乎无法使它工作,我想知道为什么/如果我能做些什么来使这个工作.test1()从我的思维方式来看,基本上应该具有与之相同的行为test3().test2()包含只是为了表明第二级事件处理工作!
events = require "events"
class ExampleEmitter extends events.EventEmitter
constructor: () ->
go1: () ->
console.log("fire 1")
@emit("test1", "there")
go2: () ->
console.log("fire 2")
@emit("test2", "there")
class ExampleHandler
constructor: () ->
handle: (x) -> console.log("hey", x)
test1 = () ->
handler = new ExampleHandler()
emitter1 = new ExampleEmitter()
emitter2 = new ExampleEmitter()
emitter1.on "test1", emitter2.go2
emitter2.on "test2", handler.handle #this doesn't fire :(
emitter1.go1()
test2 = () ->
handler = new ExampleHandler()
emitter1 = new ExampleEmitter()
emitter2 = new ExampleEmitter()
emitter1.on "test1", emitter2.go2
emitter2.on "test2", handler.handle
emitter2.go2()
test3 = () ->
handler = new ExampleHandler()
emitter1 = new ExampleEmitter()
emitter2 = new ExampleEmitter()
emitter1.on "test1", () -> emitter2.go2() #why must I wrap this?
emitter2.on "test2", handler.handle
emitter1.go1()
console.log "\ntest1"
test1()
console.log "\ntest2"
test2()
console.log "\ntest3"
test3()
Run Code Online (Sandbox Code Playgroud)
这是输出:
test1
fire 1
fire 2
test2
fire 2
hey there
test3
fire 1
fire 2
hey there
Run Code Online (Sandbox Code Playgroud)
emitter1.on "test1", () -> emitter2.go2() #why must I wrap this?
因为如果你只是传递emitter2.go2,go2将在根对象的上下文中调用(window在浏览器中;我不太了解node.js)而不是emitter2.一个函数本身并不知道它所属的对象.on实际上,您应该将闭包传递给两个调用.
为了使事情看起来更好一些,如果你的闭包不带任何参数,你可以省略括号.最终,你应该有这样的东西:
handler = new ExampleHandler()
emitter1 = new ExampleEmitter()
emitter2 = new ExampleEmitter()
emitter1.on "test1", -> emitter2.go2()
emitter2.on "test2", -> handler.handle()
emitter1.go1()
Run Code Online (Sandbox Code Playgroud)
如果你仍然不喜欢它的外观,那么下一个最好的方法是使用一个函数,通过创建这样的闭包将函数"绑定"到对象.但是,它不会为你节省任何打字,而且我觉得它看起来很丑陋且难以阅读:
bindMethod = (obj, funcName) ->
-> obj[funcName].apply(obj, arguments)
...
emitter1.on "test1", bindMethod(emitter2, 'go2')
emitter2.on "test2", bindMethod(handler, 'handle')
Run Code Online (Sandbox Code Playgroud)
最后,您可以使用胖箭头=>在类声明中创建此类绑定方法,以便您可以根据需要传递它们.go2: -> ...会成为go2: => ...,&c.但在这种情况下,我认为这是一种奇怪的行为.我坚持传递闭包,因为它使意义更清晰.