これはすべて非常に...抽象的です。
これはすべてうまくいっています。
このような抽象化の解決策を考え出すことは、必ずしもSOの目標ではありません。これは、それらを実行する方法が無数にあるためです。
ただし、いくつかの重要なポイント:
シミュレートされたコードを何らかの方法でユーザーが生成したイベントにリンクしていない限り、ブラウザーはシミュレーションがユーザーを引き継ぐのを妨げる可能性があります
(ブラウザーがページ上のJSにキー押下またはマウスクリックをシミュレートさせることを想像してください)時間)。
これは通常、ユーザーがインストール/実行する必要があるブラウザ固有の(FireFox / Chrome / IEなど)プラグインを使用する、消費者向けではないライブラリを使用する、またはバストする必要があることを意味します。1つ(または複数)を選択します。
カスタムイベントは、原則として、コールバックを使用して、プログラムを分離したまま、一緒に機能させることができます。
Zakasはサンドボックスについていくつかの素晴らしい話をしていますが、それらは非常にエンタープライズレベルのエンドゲームタイプのものです。それらは素晴らしく、ライブラリビルダーとシステムエンジニアはそれらを完全に考慮する必要がありますが、平均的なページを作成するには、ライブラリを使用して完全なフレームワークを構築するよりも、作成する必要のある100行を完成させる方がよいでしょう。これは、すべてのモジュールをエンクロージャーにラップし、それ自体をそのモジュールに注入します。
そこで、Pub-Sub(およびオブザーバー)/モデレーター(またはメディエーター)が登場します。
上記のいずれも、ライブラリに応じて、「エミッタ」または「ジェネレータ」などと呼ばれる場合があります。
上記のそれぞれは、基本的に同じ方法で作成され、同じ種類のことを行います。
目標は、聴きたい聴衆に結果を伝えることです。
スピーカーは、聴衆にいつ通知するか、何を伝えるかを選択します。
視聴者はいつでも視聴するか、次の放送を待つか(これは決して来ないかもしれませんが、少なくとも彼らはそれに注意を払っていました)、または視聴をやめて放送を聞くのをやめることを選択できます。
したがって、それらの違いは、「話者」が起こっていることをどのように知っているかということです。
パブリッシャー-サブスクライバー
ではpublisher-subscriber
、スピーカーは物事を起こすオブジェクトです。
Twitterを見てください。
Twitterアカウントにサインアップします。あなたがそれを手に入れたら、あなたはあなたが望む誰でもフォローすることができます。
彼らがツイートするたびに、あなたはそれについて通知を受けます。
誰でもあなたをフォローできるので、あなたがツイートするたびに、彼らはそれについて通知されます。
アクションを実行している人は、それを聞きたいサブスクライバーにそのアクションを公開します。3000人の購読者と1人の発行者(ニュースレター)、または3000人の発行者と1人の購読者がいる可能性があります...購読しない発行者、または発行しない購読者がいる可能性があります......しかしそれがパラダイムです。
観察者
でobserver
、あなたは仕事をしているものに結合されているオブジェクトについて話している。
きついかもしれません。緩んでいる可能性があります。しかし、何かをしていることがあり、それが何をしているのかを正確に知っていることがあります。次に、人々はウォッチャーに更新をバグします。
人々がラジオでゲームを聞いていた野球の時代を考えてみてください。
オブザーバーはラジオコメンテーターになります。
彼はボールを打ったり、盗塁したりした人ではありませんでした。彼はブースの一人で、すべてが起こっているのを見て、それが何を意味するのかを知っていて、それを家で聞いているすべての人々にとってユーザーフレンドリーな情報に変えました。
最近では、プレイヤーはプレイ中にプレイについてツイートし、ファン全員に直接ツイートすることができます(pub-sub
)。FourSquareは、手のために、ベースごとの精度まで地理を下げる方法を見つけると確信しています。三塁の王が誰であるかを更新することをオフにします(かつて、彼の窮屈なZ28ではジェフではありません)。
メディエーター/モデレーター
この場合、私たちは誰もが知っているオブジェクトについて話しているが、誰もお互いについて知らない。
コールイントークラジオショーを想像してみてください。
誰もがショーを知っています。誰でもショーに電話して、ホストと話すことができます。しかし、偶然の一致を除いて、誰も他のリスナーについて何も知りません。
誰もが出版社であるため、それは少し異なりpub-sub
ますが、誰かのTwitterハンドルを知っている必要はありません。あなたは言うことができますHey Twitter, any time anybody in the world mentions #browns, let me know. I'm starving.
。モデレーターが仕事をしている人を見ている間、誰でもいつでも仕事をすることができるので
、それは少し異なります。observer
どちらが正しいですか?
それはすべて、あなたが何を必要としているか、そしてあなたが実際にそれを使って何をしようとしているのかに依存します。
モデレーターを作成する方法は次のとおりです。
var Moderator = function () {
var events = {},
notify = function (evtName, data) {
var evt = events[evtName];
if (!evt) { return; }
evt.forEach(function (func) { func(data); });
},
listen = function (evtName, callback) {
events[evtName] = events[evtName] || [];
events[evtName].push(callback);
},
ignore = function (evtName, callback) {
var evt = events[evtName];
if (!evt) { return; }
evt.forEach(function (func, i, arr) {
if (func === callback) { arr.splice(i, 1); }
});
};
return { ignore : ignore,
listen : listen,
notify : notify };
};
とてもシンプルでわかりやすいですよね?もちろん、これは特にイベントが発生したとき、または次の3回、または何でも購読するような、鐘や笛で満たされていません...
私たちはそれを次のように使うかもしれません:
var Game = function () {
var game_moderator = Moderator(),
scoreboard = Scoreboard(),
messages = MessageBoard(),
player_one = Player(),
player_two = Player();
function initialize () {
player_one.initialize(game_moderator);
player_two.initialize(game_moderator);
game_moderator.listen("player:death", scoreboard.update);
game_moderator.listen("player:death", messages.add_kill);
game_moderator.listen("chat:input", messages.add_msg );
}
function start() {}
/* update... draw... etc... */
return {
load : load,
initialize : initialize,
start : start
};
};
var game = Game(),
loading = game.load();
loading.done(function () {
var initializing = game.initialize();
initializing.done(game.start);
});
一方、Player
次のようになります。
var Player = function (name) {
var system,
health = 30,
damage = [],
attack = function () { /* ... */ },
hurt = function (amt, type, from) {
health -= amt;
damage.push({ amount : amt, type : type, from : from });
},
die = function () {
var killing_blow = damage[damage.length - 1];
killing_blow.player = name;
system.notify("player:death", killing_blow);
},
update = function () {
if (health <= 0) { die(); }
},
draw = function () {},
initialize = function (sys) { system = sys; };
return {
initialize : initialize,
update : update,
draw : draw,
hurt : hurt
/* ... */
};
};
関数を振り返るGame.initialize
と、スコアボードとメッセージパネルがあり、どちらも「player:death」イベントで処理を実行していることがわかります。
プレーヤーの呼び出しと定義の方法のために、初期化中にモデレーターへの参照を注入しています(これにより、すべてを分離しておくことができます:依存性注入)。
しかし、何かが時々そのメソッドを呼び出して殺害情報を渡し、あらゆる種類の愛を得るということを除いて、何も知らず、何も知りませんが、それは誰もが見知らぬ人であるようなものですplayer_one
...player_two
scoreboard
.update
messages
元の問題に戻ります。
キーを押してスパイすることで埋め尽くされているのならhidden-input
、オブザーバーを作ってみませんか?
keyup
イベントリスナーとイベントリスナーに接続するオブザーバーを作成しkeydown
ます。
そのオブザーバーにそれらのイベントを有用な情報に変えてもらいます(たとえば、キーを押したままにすると、keydown
イベントは1秒間に数十回発生します-おそらくそれは望ましくありません...新しいキーが追加されたときに警告するか、押されたキーが離されたときに警告します)。
hidden-input
それを購読して もらいます。
がいっぱいの場合hidden-input
、または要件が機能している場合... ...イベントを発生させたい場合は、グローバルモデレーター(またはそのhidden-input
一部であるシステムのトップレベルにあるモデレーター)を用意します。 。
そこから、"hidden-input-filled"
または意味のあるイベントを起動します。
その出来事を気にする人々は、モデレーターを通してそのイベントを購読することができます。
つまり、もちろん、あなたのプログラムが隠された入力について誰も知らないように構築されている場合、しかし、hidden-input
のイベントについて知っておくべき人々がいます。
知っておくべきものの選択されたグループだけがありhidden-input
、それらがそのイベントについて知っている必要がある唯一のものであり、hidden-input
それらについて何かを知ることができるはずである場合は、それらを作成しますpub-sub
。
または、接続を組み合わせてください
。アイデアは、意味があり、人々に知っておくべきことを伝えるコミュニケーションを構築することです。
したがって、Twitterユーザーはサブパブである必要がありますが、ページ上のさまざまなウィジェット(タイムライン、検索、最近の写真など)は、お互いについてあまり知らないはずです(そして、すべての写真をすべてのタイムラインの更新で共有できるようにするわけではありません) )次に、ウィジェット全体が他のウィジェットと通信できるグローバルモデレーターを作成し(検索結果に基づいてタイムラインを更新する必要がある場合など)、各ウィジェット内に、さまざまな接続用のモデレーターやpub-subを配置します。コンポーネント。
それがお役に立てば幸いです。実際のイベントをハイジャックしてから、プログラムのさまざまな領域をターゲットにすることを目的とした偽のイベントを実行するよりも、これを実行することで、緩く結合された大規模なプログラムを設計する方が簡単な理由を説明できると思います。
正直なところ、すべてのプログラムを含むサイト全体が「このことを行うこの入力と、別のことを行う別の入力がある」という結果になった場合、答えは実際には問題ではないということです。多くの。
「さまざまなウィジェット用に8つのスペースがあるページがあり、これらの8つのスロットのいずれかにいつでもロードできる16の可能なウィジェットがあり、一部のウィジェットにはいくつかの主要なアクションがあります。他のウィジェットで応答を引き起こし、各ウィジェットが内部で制御する必要のあるイベントがたくさんあります。AJAXライブラリとDOM / MVC(またはMVVM)ライブラリをパイプ処理して、内部で発生するすべてのものを制御する必要があります。各ウィジェット自体、そして私は1人だけです...」
そのとき、このようなものを打ち出し、Promises / Deferreds / Futuresを打ち出し、大きなアイデアを小さな断片に分割し、実行中のアプリケーションのライフサイクルのさまざまなポイントに分散させるのは素晴らしいアイデアです。