关于事件机制的一些想法
编程    无    2016-04-04 22:22:19    556    0    3

假期 coding 中,有个需要使用事件机制的地方,但是看了几个 java 的事件机制库,感觉都好大好难用。我很疑问为什么要定义那么多的事件类型,好麻烦,难道就不能像 javascript 中那样用个字符串就定义一个事件。

首先应该有个规范

事件可能会很多,所以字符串最好有个规则。最简单的想法就是事件套命名空间,例如:

blog.event1
blog.event2

进一步看,事件往往是和动作相关联的,用另外一个分隔符以示区分,所以可能写成:

blog.article:create
blog.article.delete

再进一步看,动作并不总是一个点,它是个过程,如果写一个监听 blog.article:create 事件的响应,从名字上搞不清到底是文章创建之前调用,还是文章创建之后调用。那么就应该再加上事件的状态,这个状态就这么几种确定的,begin,doing ,done,error ,因为事件机制需要的实际上是边沿,所以实际上需要的是 before, after ,error, 用另外一种分隔符以示区别,可能会写成:

blog.article:create#before
blog.article:create#error

这样看起来就清晰了,同时也相当于实现了 AOP 的功能。如图:

pic

我只需要按照这个思路定一个规范,然后就剩下用各种编程语言实现了。

实现

同步异步

如果监听事件的响应是同步的,那么这个框架很好写了,按照状态顺序调用每个监听函数,所有监听调用结束后切换到下一个状态就行了。

但是如果监听函数是异步的,那就没法知道什么时候执行完了,这个就比较困难。

先考虑只有一个异步监听的情况。监听必须接收一个 event 参数,这个event 对象可以作为变量传递,然后在真正执行完成之后调用 done。

再考虑多个多个异步监听的情况,每个监听完成之后调用 done ,但是并不会直接进入下一个状态,只是做个标记,并检测是不是所有监听的标识都设置了,如果都设置了,才进入下一个状态。好像也没问题。

考虑异步监听和同步监听都用的情况,都采用标记的方式,也是没问题的。

这么看来,唯一的问题就是异步的监听函数必须自己调用一次 done 函数,不然事件链就断掉了。万一忘掉了,调试可能也是很麻烦。

返回值

本来还想保留返回值作为参数传递的一种方式,但是稍微想一下就会觉得挺麻烦的,还是算了,参数传递的方式很多。

并发

在js 中没有并发问题,(不包括node),但是在 java 中需要考虑并发问题。事件中心可能会建成单例的,如果一个事件的监听有好多个,那么触发函数的重入就会有问题,所以上面想到的的状态标记是要和每次触发绑定起来的。

基本上理清楚了,打算有空先做两个版本:eb4j 和 eb4js。或许动手前应该再翻翻别人的源码,看看别人怎么写的。

文档导航