コードをコピー
コードは次のとおりです:
if ( buttonClicked ) { /* 特定のアクションを実行 */ }
これは非常に結合されたソリューションです。 他の操作を追加する場合は、バインド コードを編集するか、コピーを作成する必要があります。 そうでない場合、唯一のオプションは buttonClicked をテストすることです。 buttonClicked は false である可能性があるため、新しいコードは決して実行されず、その結果、この新しいアクションが失われる可能性があります。
遅延を使用すると、より良い結果が得られます (簡単にするために、以下のコードは 1 つの要素と 1 つのイベント タイプにのみ適用されますが、複数のイベント タイプのコレクションに簡単に拡張できます):
$.fn.bindOnce = function(event, callback ) {
var element = $( this[ 0 ] ),
defer = element.data( "bind_once_defer_" イベント );
if ( !defer ) {
defer = $.Deferred() ;
関数 deferCallback() {
element.unbind(event, deferCallback );
defer.resolveWith(this, argument );
element.bind(event , deferCallback ); >element.data( "bind_once_defer_" イベント , defer );
}
return defer.done( callback ).promise();
コードは次のように動作します。
• 要素に指定されたイベントにバインドされた遅延オブジェクトがあるかどうかを確認します
• ない場合は、最初にイベントを起動するようにオブジェクトを作成します。
を解決します。 • 次に、指定されたオブジェクトをバインドします。遅延に対するコールバックと Promise を返します
コードは冗長ですが、関連する問題の処理が簡素化されます。 まずヘルパー メソッドを定義しましょう:
コードをコピーします
コードは次のとおりです: $ .fn.firstClick = function( callback ) {
return this.bindOnce( "click",
};
次に、ロジックは次のように再構築できます:
コードをコピー
コードは次のとおりです: var openPanel = $( "# myButton" ).firstClick();
openPanel.done(initializeData );
パネルが開いた後、必要なのはこれだけです:
コードをコピーします
コードは次のとおりです。 openPanel .done(function() { /* 特定のアクションを実行します */ });
パネルが開いていない場合、アクションはボタンがクリックされるまで遅延されます。
Composition Assistant
上記の例を個別に見てみると、promise の役割は限られています。 ただし、約束の本当の力は、それらを組み合わせることにあります。
パネルのコンテンツをロードし、最初のクリックでパネルを開きます
パネルを開き、そのコンテンツをリクエストしてからコンテンツをフェードインするボタンがあるとします。前に定義したヘルパー メソッドを使用すると、これを行うことができます:
コードをコピーします
コードは次のとおりです: var パネル = $( "#myPanel" ); panel.firstClick(function() {
$.when(
$.get( "panel.html" ),
panel.slideDownPromise ()
).done(function( ajaxResponse ) {
panel.html( ajaxResponse[ 0 ] ).fadeIn();
});
画像をロードし、最初のクリックでパネルを開きます
コンテンツを含むパネルがすでにあるとしますが、それが必要なのは、ボタンがクリックされたときのみです初めてクリックすると、画像がロードされ、すべての画像が正常にロードされるとフェードインします。 HTML コードは次のとおりです。
コードをコピー
data-src 属性でイメージの実パスを記述します。 このユースケースを解決するために Promise アシスタントを使用するコードは次のとおりです。
コードをコピーします
コードは次のとおりです。
$( "#myButton" ).firstClick(function() {
var panel = $( "#myPanel" ),
promises = [];
$( "img" , panel ).each(function() {
var image = $( this ), src = element.attr( "data-src" );
if ( src ) {
promises.push(
$.loadImage( src ).then( function() {
image.attr( "src", src );
}, function() {
image.attr( "src", " error.png" );
} )
);
}
});
promises.push( panel.slideDownPromise() );
$ .when.apply( null, promises ).done(function() { panel.fadeIn(); });
});
The trick here is to keep track of all LoadImage promises , then add the panel slideDown animation. So the first time the button is clicked, the panel will slideDown and the images will start loading. The panel will only fade in once you've finished sliding it down and all images have been loaded.
Load images on the page after a specific delay Suppose, we want to implement deferred image display on the entire page. To do this, the format of the HTML we need is as follows:
The meaning is very simple:
•image1.png, the third image is displayed immediately , the first image will be displayed after one second
·image2.png, the second image will be displayed after one second, and the fourth image will be displayed after two seconds
How will we achieve this?
$( "img" ).each( function() {
var element = $( this ),
src = element.attr( "data-src" ),
after = element.attr( "data-after" );
if ( src ) {
$.when(
$.loadImage( src ),
$.afterDOMReady( after )
).then(function() {
element.attr( " src", src );
}, function() {
element.attr( "src", "error.png" );
} ).done(function() {
element. fadeIn();
});
}
});
If we want to lazy load the image itself, the code will be different:
$( "img" ).each(function() {
var element = $( this ),
src = element.attr( "data-src" ),
after = element.attr( "data-after" );
if ( src ) {
$.afterDOMReady( after, function() {
$.loadImage( src ).then(function() {
element.attr( "src", src );
}, function() {
element.attr( "src", "error.png" );
} ).done(function() {
element.fadeIn();
});
} );
}
});
Here, we first wait for the delay condition to be met before trying to load the image. This makes sense when you want to limit the number of network requests while a page is loading.
Conclusion As you can see, promises are very useful even without Ajax requests. By using the deferred implementation in jQuery 1.5, it is very easy to separate asynchronous tasks from your code. This way, you can easily separate logic from your application.