22

私には2つの抽象化されたプロセスがあり(たとえば、内部を公開しない公開モジュールパターンを使用してjsオブジェクト内で管理されます)、完了時にカスタムイベントを発生させます。両方のカスタムイベントが発生したときにアクションを実行したいと思います。

jQuery 1.5の新しいDeferredロジックは、これを管理するための理想的な方法のようです。ただし、when()メソッドは、promise()(または通常のjsオブジェクト)を返すDeferredオブジェクトを取得しますが、when()は、代わりにすぐに完了します。待っている、それは私には役に立たない)。

理想的には、次のようなことをしたいと思います。

//execute when both customevent1 and customevent2 have been fired
$.when('customevent1 customevent2').done(function(){
  //do something
});

これらの2つのテクニックを組み合わせる最良の方法は何でしょうか?

4

2 に答える 2

40

http://jsfiddle.net/ch47n/

新しいjQuery.fn.whenメソッドを作成する小さなプラグインを作成しました。

構文は次のとおりです。

jQuery( "whatever" ).when( "event1 event2..." ).done( callback );

内部でjQuery.when()を広範囲に使用し、解決する前にコレクション内のすべての要素ですべてのイベントがトリガーされていることを確認します。


以下の実際のプラグインコード:

( function( $ ) {

    $.fn.when = function( events ) {

        var deferred, $element, elemIndex, eventIndex;

        // Get the list of events
        events = events.split( /\s+/g );

        // We will store one deferred per event and per element
        var deferreds = [];

        // For each element
        for( elemIndex = 0; elemIndex < this.length; elemIndex++ ) {
            $element = $( this[ elemIndex ] );
            // For each event
            for ( eventIndex = 0; eventIndex < events.length; eventIndex++ ) {
                // Store a Deferred...
                deferreds.push(( deferred = $.Deferred() ));
                // ... that is resolved when the event is fired on this element
                $element.one( events[ eventIndex ], deferred.resolve );
            }
        }

        // Return a promise resolved once all events fired on all elements
        return $.when.apply( null, deferreds );
    };

} )( jQuery );
于 2011-02-16T03:43:41.617 に答える
12

「customevent1」と「customevent2」のイベントハンドラーは、それぞれが起動したときに「Deferred」インスタンスにシグナルを送るようにすることができます。次に、「$。when()」を使用して、これら2つを1つに結合できます。ここで、両方のカスタムイベントが発生した後にのみハンドラーを発生させます。

var df1 = $.Deferred(), df2 = $.Deferred();
$('whatever').bind('customevent1', function() {
  // code code code
  df1.resolve();
}).bind('customevent2', function() {
  // code code code
  df2.resolve();
});

var whenBoth = $.when(df1, df2);

whenBoth.then(function() {
  // code to run after both "customevent1"
  // and "customevent2" have fired
});

古い答え、完全を期すためにここに

2つの条件を追跡し、両方が設定されている場合に「解決」を実行する独自のDeferredオブジェクトを作成できます。

function watchEvents() {
  var df = $.Deferred();

  var flags = {};
  $.each(Array.prototype.slice.call(arguments, 0), function() {
    flags[this] = false;
  });

  var realResolve = df.resolve.bind(df);
  df.resolve = function(eventName) {
    flags[eventName] = true;
    for (var ev in flags) if (flags[ev] === false) return;
    realResolve();
  };

  return df;
}

これで、その関数を呼び出すことができます。

var df = watchEvents("customevent1", "customevent2");

そして今、それらのイベントのイベントハンドラーは、イベントをキャッチするときに、そのことについて「resolve」を呼び出す必要があります。

    df.resolve(event.type);

各ハンドラーは独自のタイプを報告します。「watchEvents」を呼び出したときに要求されたすべてのイベントタイプが発生した場合にのみ、「df」に登録したハンドラー関数が実際に呼び出されます。

別の方法として、要素のDeferredオブジェクトを初期化して「.data()」プロパティに格納するjQueryプラグインを作成することもできます。次に、イベントハンドラーが自分自身に信号を送るために使用できるプラグインや、マルチイベントシーケンスのハンドラーを登録するための他のプラグインを作成できます。それはかなりクールだと思いますが、私はそれを熟考するのに少し時間を費やす必要があります。

于 2011-02-15T20:56:09.603 に答える