nsIObserverServiceを使って複数のobserverに通知を行う

FirefoxやThunderbirdの拡張を作る際に、場合によっては非同期処理が入ったりします。

XPCOMではそのような場面でobserverが簡単に仕込める仕組みとして、nsIObserverServiceと言うインターフェ−スがあるので、今回はその使い方についてご紹介します。

ObserverServiceの概要

そもそもnsIObserverServiceには下記のようなメソッドが定義されています。

  • addObserver()
  • removeObserver()
  • notifyObservers()
  • enumerateObservers()

以下簡単にそれぞれについて触れてみます。

addObserver, removeObserver
特定のtopicに対して通知を受け取るobserverオブジェクトを設定したり消したり出来ます。
notifyObservers()
特定のtopicを監視する全てのobserverに対して通知します
enumerateObservers()
特定のtopicを監視するobserverをenumerationとして取得します。

observerの作り方

nsIObserverと言うインターフェースが存在しますので、その型を実装すれば問題無く使えます。


var testObserver = {
  observe: function(subject, topic, data) {
    if (topic != "testTopic") {
      return;
    }

    repl.print(({
      "subject": subject,
      "topic": topic,
      "data": data
    }).toSource());
  }
};

と言う訳でobserveメソッドを持つ適当なオブジェクトを上記のように作れば、後はnotifyがあればその通知を受け取る事が出来ます。

ちなみにMozRepl経由で確認すると楽に出来ます。
他の方法で見る方はalertなりerror consoleなりお好きな所に出力して下さい。

observerの登録

windowのload, unloadイベントでaddObserver(), removeObserver()を呼び出す処理を追記したobserverだと下記のようになります。


var testObserver = {
  observerService: null,
  init: function() {
    testObserver.observerService = Components.classes["@mozilla.org/observer-service;1"]
      .getService(Components.interfaces.nsIObserverService);
    testObserver.observerService.addObserver(testObserver, "testTopic", false);
  },
  observe: function(subject, topic, data) {
    if (topic != "testTopic") {
      return;
    }

    repl.print(({
      "subject": subject,
      "topic": topic,
      "data": data
    }).toSource());
  },
  complete: function() {
    testObserver.observerService.removeObserver(testObserver, "testTopic");
  }
};

testObserver.init, testObserver.completeは適当な場所で呼び出すようにしておきます。(例えばload, unloadイベントにaddEventListenerとして)

observalな処理の中でnotifyObserversを使う

例えばですが、長く掛かる処理と言うのをsetTimeoutで表現したとして、


var TestObserval = function() {
  this.observerService = Components.classes["@mozilla.org/observer-service;1"]
    .getService(Components.interfaces.nsIObserverService);
}

TestObserval.prototype = {
  observerService: null,
  start: function() {
    this.observerService.notifyObservers(null, "testTopic", "start");
    setTimeout(this.process, 3000);
  },
  process: function() {
    this.observerService.notifyObservers(null, "testTopic", "end");
  }
}    

としてあげて、オブジェクトを生成してstart()を実行してあげると、実際にnotifyが届いている事が分かると思います。

comment

Comment Form
remember info

trackback

trackback url
trackback count
0
Recent Entries
  1. perlで気軽にsitemap.xmlを作る
  2. XULでCanvasエディターを作ってみた
  3. nsIObserverServiceを使って複数のobserverに通知を行う
  4. CGI::Application::Plugin::Cache::Adaptive Release
  5. Gearmanを使ってみた
  6. 「正しくHTMLを書こうと心がけている人に5つの質問」の回答
  7. Modules in Games-Nintendo-Wii-Mii
  8. Module-Starterのカスタマイズ
  9. JSON::DWIW vs JSON::Syck vs JSON
  10. よろしくお願い致します
Archives
  1. 2008年02月 (1)
  2. 2007年06月 (2)
  3. 2007年05月 (1)
  4. 2007年04月 (4)
  5. 2007年03月 (2)

all

categories
RSS/Atom Feed
license
Creative Commons License
Powered by