本文介绍基于事件编程的基础思想,用JavaScript代码表达(伪代码,不可执行)。
想象一下这个场景,明天你跟你家妞约好出去玩,你很想知道明天的天气怎样,于是你就打电话去气象站问,但是你不知道气象站什么时候能出结果,于是你就隔段时间打个电话问问,不停的打,然后人家被你弄烦了,不理你了。 这样做多不好,多不nice啊,于是你改变方法,跟气象站这么说:“您好,我很想知道明天的天气,这是我的电话号码,如果天气预报结果出来后,麻烦给我个电话,谢谢!”。过了段时间,气象站的工作人员打电话告诉你,明儿个是个大晴天,于是你高高兴兴的和你家妞出去玩了。。。。(OK,YY结束,回来现实世界(苦逼的单身汉))。
将上面的场景抽象(你不断的打电话给别人)一下,用JavaScript表示的话,
var weatherStation = { result: null startWork: function() { //处理收集的数据,计算中。。。 if (结果出来了) { this.result = 结果 } }, answer: function (question) { return result; } }; var theBoy = { getWeatherInfo: function () { //隔一个小时打个电话 setTimeout(this.callWeatherStation, 3600000); }, callWeatherStation : function() { weatherStation.answer(); } }; weatherStation.startWork(); theBoy. getWeatherInfo();
换种处事方式(说话客气点,让别人打电话给你),换种代码:
var weatherStation = { result: null, callbackPhoneNumber: [], startWork: function() { var i = 0; //处理收集的数据,计算中。。。 if (结果出来了) { for(; i < this.callbackPhoneNumber.length; i++) { //其中肯定有打给我的电话,嘿嘿。。。。 this.call(this.callbackPhoneNumber[i]); } } }, tellMe : function (phoneNumber) { this.callbackPhoneNumber.push(phoneNumber); }, call : function (phoneNumber) { //调用我就可以打电话了 } }; var theBoy = { getWeatherInfo: function () { weatherStation.tellMe('137XXXXX543'); } }; weatherStation.startWork(); theBoy. getWeatherInfo();
生活中第二种处事方式,不仅使你不用隔段时间打个电话,能专心的做事,也能让气象站的工作人员免遭你的骚扰,早点计算出结果,与人与己都好。其实抽象成代码也一样,第二种方式能很好的解耦,提高内聚(每个对象做好自己的事情)。这么有用模式在其他场景肯定也会用到,当然要抽象出来,以供代码重用。
在整个事件中,最关键的是气象站什么时候算出天气预报,这是个很重要的事件,大家关心的都是这个事件,不管是“我”还是“气象管理员”谁给谁打电话,都是想要找计算出结果的那个时刻。好,我们来抽象这个事件。事件有几个要素,一:这个事件是谁的,也就是说谁可以触发这个事件,即:事件源;二:这个事件谁关心的,如果你想关心这个事件,你如何关心这个事件,即:事件的绑定;三:如果你知道发生了这个事件,你想要干什么呢?即:事件的处理。抽象成JS代码如下:
var Events = { bind: function (eventName, callback) { this.callbacks = this.callbacks || {}; this.callbacks[eventName] = []; this.callbacks.push(callback); }, trigger : function (eventName) { var i = 0; if ( !this.callbacks) { return this; } if ( !this.callbacks[evntName]) { return this; } for(; i < this.callbacks[eventName].length; i++) { this.callbacks[eventName].apply(this); } } };
如果某个对象具有事件的特性,只需要继承或混淆(mixed)Events对象到你想要的对象。“某个对象”会就有bind和trigger方法,即绑定事件和触发事件,而某对象本身成为了事件源。
最终我们的代码可以这样写:
var weatherStation = { startWork: function() { var i = 0; //处理收集的数据,计算中。。。 if (结果出来了) { this.trigger('finished'); } } }; jQuery.extend(weatherStation, Events); var theBoy = { getWeatherInfo: function () { weatherStation.bind('finished', function () { call('137XXXXX543'); }) ; } }; weatherStation.startWork(); theBoy. getWeatherInfo();
未完待续。。。。