跳到主要內容

[分享] 範例續談 event emitter - explain how event emitter works for js Class

EventEmitter

之前有介紹過 Event Emitter 程式運作基本架構,通常大家在瀏覽器中經常使用 Event 註冊方法,設置 callback 讓程式能夠採用 event-driven 的方式進行。

在 Node.js 裡面,很多時刻是面臨到自己要去設計程式流程,而不是只有等待某個程式建立好之後,我們去使用而已。

在程式的觸發上,今天來介紹一下到底程式開發上有什麼差異。

引用例子

這邊採用車子加油的例子來說好了。

完整程式範例

舊有架構

如果採用舊有的架構,首先我們要有一台車子,這台車子是沒有加油的狀態。

function Car() {
    _oil = 0
}

module.exports = Car;

接著要開個開口(_addOilHandler),讓車子可以加油,這是一台聰明車,所以可以自動把油加滿。

  _addOilHandler = function () {

    if(_oil >= 100) {

      _oil = 100;

    } else {

      _oil += _oilInterval;

      // call self again.
      setTimeout(function() {
        _addOilHandler(_oilInterval);
      }, INTERVAL);
    }   

  };
看起來,一個會自動加油的車子就這樣子建構完成。

接著,程式要執行了,雖然這是一台會自動加油的車子,不過身為操作者的我們,還是要去檢查是否加油已經加滿,否則我們也不知道什麼時候可以開車。

以下就是檢查的方式。

var OldCar = require('./OldCar');
var bubu = new OldCar();

bubu.setOilInterval(10);
bubu.start();

看起來好像沒有什麼問題,可是卻發現,車子油加滿之後,並沒有進行任何通知,因此我們要增加進行持續檢查的機制。不斷的回頭看一下,什麼時候油滿了沒,持續詢問,當滿的時候才顯示訊息,因此增加程式如下,

(function () {
  if (bubu.getCurrentOil() >= 100) {                                                                                                                                              
    console.log('[STATUS] setTimeout Oil is full');
  } else {
    setTimeout(arguments.callee, 50);
  }
})();

Event driven 全新架構

看起來上面的車子已經很聰明了,不過似乎少了一點什麼,如果車子內部機制調整一下,當一開始的時候就跟車子說,油加滿請跟我說,當油真的加滿的時候,請回應給我,因此調整一下新車架構。

function Car() {

  var Emitter = require('events').EventEmitter,                                                                                                                                   
      emitter = new Emitter();
      
  const FINISH_EVENT = 'add_oil_done';

}
先將事件觸發的功能擺入,這邊先慶幸自己是採用 Node.js ,已經提供了 EventEmitter 機制,讓車子可以進行全新改裝。

接著要將接口打開,提供一個人車端口,讓我們可以跟車子說,『當油加滿的時候請通知我』,程式如下,

  addOil = function (callback) {
    emitter.on(FINISH_EVENT, callback);
    return this;
  };
接下來改進 _addOilHandler 程式,

這個時候改裝已經差不多,剩下回應的時間點,當油加滿之後,必須要將剛才使用者註冊的『當油加滿的時候請通知我』進行通知,因此需要有一個觸發點,觸發程式點就是在油量達到 100 的時候進行回饋。

  _addOilHandler = function () {

    if(_oil >= 100) {

      _oil = 100;
      emitter.emit(FINISH_EVENT, null, '[STATUS] Oil is full');

    } else {

      _oil += _oilInterval;

      // call self again.
      setTimeout(function() {
        _addOilHandler(_oilInterval);
      }, INTERVAL);
    }

  };

全新程式測試

看起來宇宙最夢幻的車子從此誕生,接下來進行最後人機測試。
var Car = require('./Car');
var bubu = new Car();

bubu.setOilInterval(10);
bubu.addOil(function (err, status) {
  console.log(status + ', [STATUS] callback mode');
}).start();

看起來的確程式簡潔許多,而且能夠在最準確的時間回應駕駛,讓我們知道什麼時候油可以加滿,立刻進行通知動作。

結語

可以從上面的程式改寫,看到在 event-driven 的差異。

以往的狀態,如果沒有使用事件驅動的方式,會導致需要使用不斷回頭檢查機制,進行確認,當然這樣並不會太難做,可是卻會浪費效能在回頭檢查上,而且會造成『檢查事件』的時間差異。

利用 Event emitter 的特長,可以在 Class 中簡單進行 Event-driven 的運作,讓操作行為更為簡單。

留言

這個網誌中的熱門文章

[CSS] z-index 在不同瀏覽器繼承問題

今天會討論到這個課題,是因為要實做一個Popup dialog,所以我們希望的結果如下圖。 可是在IE7 卻發生了這樣的情況。 Popup不論怎麼設定z-index都無法浮在最上層,我們看一下html架構發生什麼事情。

[教學] 快快樂樂刪除CodeIgniter index.php

預設的CI網址預設都設定為index.php同一層級,因此所有的程式都必須指定index.php導向才能開始,例如 http://localhost/ci/index.php/welcome/test http://localhost/ci/welcome/test 本文將說明如何將惱人的index.php消除,還你一個漂亮的URL。 設定開始: 接下來說明如何使用rewrite方式將惱人的index.php去除。 rewrite不清楚的人,煩請先自行google 首先要先確定Apache的 mod_rewrite 有 開啟 ,如果沒有開啟請設定好之後重新啟動apache。 接著,在根目錄底下建立一個新檔案,檔名為 .htaccess ,裡面程式碼如下: <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [L] </IfModule> 接著到 application/config/config.php ,開啟檔案修改 $config['index_page'] = ""; 注意: /index.php/$1 要根據你目錄,例如 http://localhost/index.php ,網站根目錄為 /ci/index.php 則要寫成 /ci/index.php/$1 接著至CI目錄下,尋找 config\config.php , 修改一下裡面的檔案,修改如下: $config['index_page'] = ""; 存檔後,如此一來大功告成。 參考資料 官方網站說明

[教學] Mojito 安裝與入門,install mojito for beginner.

mojito ,最近終於從 YDN 對外公開此專案,這個套件主要用於解決前端多重裝置及瀏覽器端的問題,後端服務採取 node.js ,因此使用上必定要先準備以下幾個元素 準備素材 c++ complier git Node.js > 0.4.x NPM > 1.0.x 安裝方式 git clone git://github.com/yahoo/mojito.git cd mojito/source sudo npm install -g . npm install . 以上四個簡單的步驟,就可以把 mojito module 完整安裝到服務器上,接著就可以開始進入 mojito 的世界 使用方式 mojito 提供了完整的 command line 給開發者使用,接著先建立一個基本 hello world 專案,跟著以下步驟完成第一個專案。首先建立一個 mojito application, mojito create app hello cd hello 切換到目錄之後,再接著建立自己的 mojit,這邊的 mojit 就像是一個應用(application)可能會包含許多個獨立網站體,擁有獨立架構的 MVC ,包含內部設定等,詳細資料可以參考官方的 說明 ,建立 mojit mojito create mojit HelloMojit 輸入指令後,會看到顯示結果如下, creating mojit called 'HelloMojit' (using "default" archetype) ✔ mojit: HelloMojit created! ✔ mojito done. 接著修改 application.json 這個 mojit 設定檔案,讓剛才新建立的 hellp application 指定底下有一個 mojit -> HelloMojit ,讓應用可以去執行 mojit controller ,修改如下, [ { "settings": [ "master" ], "appPort": 8666, "specs": { ...