web-dev-qa-db-ja.com

いつJQuery.Callbacksを使用しますか?

私はjQuery 1.7に追加された新しいものを調べていたところ、jQuery.Callbacks() http://api.jquery.com/jQuery.Callbacks/ が追加されていることがわかりました。

ドキュメントには、jQuery.callbacks()の使用方法が示されていますが、使用したい場合の適切な例はありません。

コールバックリストからコールバックを追加/削除でき、jQuery.callbacks()。fire(args)を実行できるようですが、これはそのリスト内のすべてのコールバックを起動するだけです。多分私は何かが足りないのですが、これはあまり役に立ちません。

この新しい機能を初めて見たときの頭の中では、キーと値のペアで使用できると思いました。これにより、アプリケーションの1か所でコールバック関数を管理する簡単な方法が提供されます。何かのようなもの

$.callbacks.add("foo", myFunction);

そして、たとえば、関数の最後にそのコールバックを呼び出したい場合は、次のようにすることができます

$.callbacks().fire("foo", args);

ただし、特定のコールバックを起動できるようには見えません。指定された引数を持つすべてのコールバックのみを起動するか、それらを起動しないようにできます。

私が見た最も近いものは、「this」プロパティを設定するためのコンテキストを.fire()関数に与える機能を与えられていた

.fireWith(context, args)

しかし、これも実際にはあまり役に立ちません。

  1. ドキュメントを誤解していますか?

  2. これが望ましい機能である場合、これが役立ついくつかの適用可能な例があります。

41
Keith.Abramo

@ Rockets answer を少し拡張して、混乱を解消するには:

JQueryの$.Callbacksを使用する必要がある理由は多面的です。

  1. ユーザーが1つの関数に多くのコードを持ち、それを分割したい
  2. 彼らはその情報を取得し、jQueryコールバック関数を介して送信します。これにより、コードを処理しやすいようにコードを分割しやすくなります。
    (たとえば) @ Rocketのコード を見ると、次のようになります。

    var clickCallbacks = $.Callbacks();
    
    clickCallbacks.add(function() { //one one function piece
        //parse and do something on the scope of `this`
        var c = parseInt(this.text(), 10);
        this.text(c + 1);
    });
    clickCallbacks.add(function(id) { //add a second non-related function piece
        //do something with the arguments that were passed
        $('span', '#last').text(id);
    });
    
    $('.click').click(function() {
        var $ele = $(this).next('div').find('[id^="clickCount"]');
        clickCallbacks.fireWith($ele, [this.id]); //do two separate but related things.
    });
    
  3. 現在使用できるのは、コード全体にそれほど多くの変更を加える必要なく、必要であると判断したときにいつでも呼び出すことができる関数の複数のコールバックバッチです。
16

同じメソッドを使用して異なるDOM要素を更新しているときに、コールバックが役立つことがわかります。

これは安っぽい例です: http://jsfiddle.net/UX5Ln/

var clickCallbacks = $.Callbacks();

clickCallbacks.add(function() {
    var c = parseInt(this.text(), 10);
    this.text(c + 1);
});
clickCallbacks.add(function(id) {
    $('span', '#last').text(id);
});

$('.click').click(function() {
    var $ele = $(this).next('div').find('[id^="clickCount"]');
    clickCallbacks.fireWith($ele, [this.id]);
});

何かをクリックすると、クリックカウンターと「ラストクリック」が更新されます。

12
Rocket Hazmat

(ほぼ)すぐに使えるjQuery Pub/Subシステム

これはIMHOの最も興味深いアプリケーションであり、回答にclearlyが記載されていなかったため(使用法を示唆する人もいますが)、この比較的古い投稿に追加しています。

NB:jQuery docs の例で使用法が明確に示されていますが、その後に追加されたと思います質問が投稿されました。

Pub/sub 、別名オブザーバーパターンは、アプリケーションで疎結合および単一の責任を促進するパターンです。 。オブジェクトが他のオブジェクトのメソッドを直接呼び出すのではなく、オブジェクトは代わりに特定のタスクまたはアクティビティにサブスクライブし、それが発生したときに通知されます。 Pub/Subパターンを使用する利点の詳細な説明については、 (JS/jQueryで)パブリッシュ/サブスクライブパターンを使用する理由 を確認できます。

確かに、 これはカスタムイベントで可能でしたtrigger.on()および.off()を使用していますが、jQuery.Callbacksは、タスクにより適したロットになり、よりクリーンなコードが生成されます。

jQueryドキュメント のサンプルスニペットを次に示します。

var topics = {};

jQuery.Topic = function( id ) {
    var callbacks,
        method,
        topic = id && topics[ id ];

    if ( !topic ) {
        callbacks = jQuery.Callbacks();
        topic = {
            publish: callbacks.fire,
            subscribe: callbacks.add,
            unsubscribe: callbacks.remove
        };
        if ( id ) {
            topics[ id ] = topic;
        }
    }
    return topic;
};

そして使用例:

// Subscribers
$.Topic( "mailArrived" ).subscribe( fn1 );
$.Topic( "mailArrived" ).subscribe( fn2 );
$.Topic( "mailSent" ).subscribe( fn1 );

// Publisher
$.Topic( "mailArrived" ).publish( "hello world!" );
$.Topic( "mailSent" ).publish( "woo! mail!" );

// Here, "hello world!" gets pushed to fn1 and fn2
// when the "mailArrived" notification is published
// with "woo! mail!" also being pushed to fn1 when
// the "mailSent" notification is published.

/*
output:
hello world!
fn2 says: hello world!
woo! mail!
*/
8
edsioufi

_$.Callbacks_は実装の詳細として始まったようです。関数のリストを管理し、指定されたリスト内のすべての関数を同じ引数で呼び出す手段です。 C#の マルチキャストデリゲート に少し似ており、リストの動作をカスタマイズするために渡すことができるフラグなどの追加機能を備えています。

良い例は、jQueryが_$.Callbacks_を内部的に使用してreadyイベントを実装することです。 bindReady()は、コールバックリストを初期化します。

_readyList = jQuery.Callbacks( "once memory" );
_

onceフラグとmemoryフラグに注意してください。これにより、コールバックリストが1回だけ呼び出され、リストが呼び出された後に追加された関数がすぐに呼び出されます。

次に、ready()は、指定されたハンドラーをそのリストに追加します。

_ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();

    // Add the callback
    readyList.add( fn );

    return this;
}
_

最後に、DOMの準備ができると、コールバックリストが呼び出されます。

_readyList.fireWith( document, [ jQuery ] );
_

すべてのreadyハンドラーは、グローバルjQueryオブジェクトへの同じ参照を使用して、同じドキュメントのコンテキストで呼び出されます。これらは一度だけ呼び出すことができ、ready()に渡された追加のハンドラーはその後すぐに呼び出されます。これはすべて_$.Callbacks_の好意によるものです。

3

コンテキストの設定に関する具体的な言及はありませんが、任意の数の引数を渡すことができるため、役立つ可能性があります。また、フラグを最初の引数として渡す独自の規則を作成し、残りの引数リストを処理する意図がない場合は、リスナーがすぐにfalseを返すようにすることもできます。

このようなものが役に立つかもしれないケースに遭遇しましたが、代わりにカスタムイベントでbind()とtrigger()を使用しました。サービスをポーリングして新しいメッセージを探すメッセージ処理システム(Webベースのチャットルームまたは電子メールクライアント)を想像してみてください。 1つの機能は、スパンに数値を設定することや、何かが発生したときにうなりを表示することです。もう1つはグリッドを更新している可能性があります。トリガーを使用する場合、リスナーごとにイベントをトリガーし、渡された引数をeventDataから「アンロール」する必要があります。コールバックは1回の起動で、リスナーは単純な引数リストを持つ単純なJavaScript関数です。

コールバックは革命的なものではありませんが、コードが少なくてすっきりします。

2
flesk

多くのビジネスロジックと少なくとも11の外部サービスを備えたアプリに取り組んでいます。 Deferred実装に意志を強制するのではなく、コールバックなどを使用して独自のフロー制御クラスと動作を記述できれば、物事をまっすぐに保つのに役立ちます。

0
AutoSponge