jQuery Deferred と Promise_jquery を使用した応答性の高いアプリケーションの作成に関する詳細な紹介
この記事では、JavaScript における Deferred と Promise の概念について説明します。これらは JavaScript ツールキット (Dojo や MochiKit など) の非常に重要な機能であり、最近、人気のある JavaScript ライブラリ jQuery (すでにバージョン 1.5 で導入されています) でデビューしました。 。 Deferred は、将来のある時点で応答を返すことを目的とした「promise」オブジェクトを作成することにより、抽象的な非ブロッキング ソリューション (Ajax リクエストへの応答など) を提供します。これまで「約束」に出会ったことがない場合は、以下で詳しく説明します。
抽象的に言えば、遅延は、ブロック関数と比較して、アプリケーションが完了するのをブロックするのではなく、完了までに時間がかかる操作を表す方法として理解できます。そして結果を返します。遅延オブジェクトはすぐに戻ります。その後、コールバック関数を遅延オブジェクトにバインドできます。コールバック関数は、非同期処理の完了後に呼び出されます。
Promise
Promise と deferred の実装の詳細に関する情報を読んだことがあるかもしれません。この章では、Promise がどのように機能するかを簡単に紹介します。これは、遅延をサポートするほとんどすべての JavaScript フレームワークに適用できます。
一般に、Promise は、ソフトウェア エンジニアリングにおける遅延 (または将来) の概念を説明するための解決策を提供するモデルとして機能します。その背後にある考え方はすでに紹介されています。メソッドを実行して結果が返されるのを待つアプリケーションをブロックする代わりに、将来の値を満たすために Promise オブジェクトが返されます。
サードパーティ API からのデータに大きく依存する Web アプリケーションを構築すると、理解に役立ちます。その場合、よくある問題に直面します。API 応答の遅延時間を知ることができず、結果が返されるまでアプリケーションの他の部分がブロックされる可能性があります。遅延は、ノンブロッキングでコードから完全に切り離されているため、この問題に対するより良い解決策を提供します。
Promise/プロポーザルは、ハンドラー関数が結果を返すときに実行されるコールバックを登録するための「then」メソッドを定義します。 Promise を返すための疑似コードは次のようになります:
promise = callToAPI( arg1, arg2, ...);
promise.then(function( futureValue ) {
/* ハンドル futureValue */
}); (function( futureValue ) {
/* do something else */
});
•resolved: この場合、データは利用可能です
•rejected: この場合、エラーが発生し、利用可能な値はありません
幸いなことに、「then」メソッドは 2 つのパラメータを受け入れます。 1 つは約束が解決されたとき (resolved) で、もう 1 つは約束が拒否されたとき (rejected) です。疑似コードに戻りましょう:
/* 値を取得しました */
} , function() {
/* 何か問題がありました */
} ); >
場合によっては、アプリケーションを続行する前に複数の結果を取得する必要があります (たとえば、ユーザーが関心のあるオプションを選択する前に、動的なオプションのセットを表示するなど)。この場合、「when」メソッドを使用して、すべての約束が満たされた後にのみ実行を続行できるというシナリオを解決できます。
promise2,
...
).then(function( futureValue1, futureValue2, ... ) {
/* すべての Promise が完了し、解決されています */
});
その良い例は、複数のアニメーションを同時に実行するシナリオです。 各アニメーション実行後のコールバックを追跡しないと、アニメーションの完了後に次のタスクを実行することが困難になります。ただし、Promise と 'when' メソッドを使用すると、非常に簡単になります。アニメーションが完了したら、次のタスクを実行できます。最終的な結果は、コールバックを使用するだけで、複数のアニメーションの実行結果を待機する問題を解決できることです。 例:
/* プロミス 1 を返す */
}, function(){
/* アニメーション 2 */
/* プロミス 2 を返す */
} ).then(function(){
/* 両方のアニメーションが完了したら、追加のロジックを実行できます */
});
这意味着,基本上可以用非阻塞的逻辑方式编写代码并异步执行。 而不是直接将回调传递给函数,这可能会导致紧耦合的接口,通过promise模式可以很容易区分同步和异步的概念。
在下一节中,我们将着眼于jQuery实现的deferreds,你可能会发现它明显比现在所看到的promise模式要简单。
jQuery的Deferreds
jQuery在1.5版本中首次引入了deferreds。它 所实现的方法与我们之前描述的抽象的概念没有大的差别。原则上,你获得了在未来某个时候得到‘延时'返回值的能力。在此之前是无法单独使用的。 Deferreds 作为对ajax模块较大重写的一部分添加进来,它遵循了CommonJS的promise/ A设计。1.5和先前的版本包含deferred功能,可以使$.ajax() 接收调用完成及请求出错的回调,但却存在严重的耦合。开发人员通常会使用其他库或工具包来处理延迟任务。新版本的jQuery提供了一些增强的方式来管理 回调,提供更加灵活的方式建立回调,而不用关心原始的回调是否已经触发。 同时值得注意的是,jQuery的递延对象支持多个回调绑定多个任务,任务本身可以既可以是同步也可以是异步的。
您可以浏览下表中的递延功能,有助于了解哪些功能是你需要的:
jQuery.Deferred() | 创建一个新的Deferred对象的构造函数,可以带一个可选的函数参数,它会在构造完成后被调用。 |
jQuery.when() | 通过该方式来执行基于一个或多个表示异步任务的对象上的回调函数 |
jQuery.ajax() | 执行异步Ajax请求,返回实现了promise接口的jqXHR对象 |
deferred.then(resolveCallback,rejectCallback) | 添加处理程序被调用时,递延对象得到解决或者拒绝的回调。 |
deferred.done() |
当延迟成功时调用一个函数或者数组函数. |
deferred.fail() |
当延迟失败时调用一个函数或者数组函数.。 |
deferred.resolve(ARG1,ARG2,...) | 调用Deferred对象注册的‘done'回调函数并传递参数 |
deferred.resolveWith(context,args) | 调用Deferred对象注册的‘done'回调函数并传递参数和设置回调上下文 |
deferred.isResolved | 确定一个Deferred对象是否已经解决。 |
deferred.reject(arg1,arg2,...) | 调用Deferred对象注册的‘fail'回调函数并传递参数 |
deferred.rejectWith(context,args) | 调用Deferred对象注册的‘fail'回调函数并传递参数和设置回调上下文 |
deferred.promise() | 返回promise对象,这是一个伪造的deferred对象:它基于deferred并且不能改变状态所以可以被安全的传递 |
jQuery 遅延実装の中核は、チェーン内で呼び出すことができるコンストラクターである jQuery.Deferred です。 ...遅延オブジェクトのデフォルト状態は未解決であり、コールバックは .then() または .fail() メソッドを通じてキューに追加され、プロセスの後半で実行されることに注意してください。
複数のパラメーターを受け入れる $.when() の次の例
関数 successFunc(){ console.log( "成功!" ) }
関数 FailureFunc(){ console.log( "失敗!" ); $.when(
$.ajax( "/main.php" ),
$.ajax( "/modules.php" ),
$.ajax( "/lists.php" )
) .then( successFunc, FailureFunc );
$.when() の実装で興味深いのは、遅延オブジェクトを解析できるだけでなく、そうでないパラメータも渡すことができることです。遅延オブジェクトは処理時に遅延オブジェクトとして扱われ、コールバック (doneCallbacks) がすぐに実行されます。 これは、jQuery の Deferred 実装でも言及する価値があります。さらに、 deferred.then() は、遅延のキューにコールバックを追加するための deferred.done メソッドと deferred.fail() メソッドのサポートも提供します。
前に紹介した表に記載されている deferred 関数を使用して、コード例を見てみましょう。 ここでは、非常に基本的なアプリケーションを作成します。(1) $.get メソッド (Promise を返す) を介して外部ニュース ソースを取得し、(2) 最新の応答を取得します。 同時に、プログラムは関数 (prepareInterface()) を通じてニュースと返信コンテンツ表示コンテナーのアニメーションも実装します。
他の関連アクションを実行する前に上記の 3 つの手順が確実に完了するように、$.when() を使用します。 .then() ハンドラーと .fail() ハンドラーを使用して、ニーズに応じて他のプログラム ロジックを実行できます。
console.log( “受信したニュースデータ” );
$( “.news” ).html(data);
} ) ;
}
function getlatestReactions() {
return $.get( “latestReactions.php”, function(data){
console.log( “受信したリアクションデータ” );
$ ( ".reactions" ).html(data);
} );
function prepareInterface() {
return $.Deferred(function( dfd ) {
varlatest = $( ".news, .reactions" );
latest.slideDown( 500, dfd.resolve );
latest.addClass( "active" ).promise( );
}
$.when(
getlatestNews(), getlatestReactions(), prepareInterface()
).then(function(){
console.log( “fireリクエストが成功した後 ” );
}).fail(function(){
console.log( “何か問題が発生しました!” );
});
が遅延しましたajax のシーン 運用で使用しても、他の場所では使用できないというわけではありません。 このセクションでは、遅延を使用することで非同期動作を抽象化し、コードを分離するのに役立ついくつかのソリューションを見ていきます。
非同期タスクに関しては、タスクが同じキーに対して 1 回だけ実行されるようにする必要があるため、キャッシュは少し要求が厳しい場合があります。したがって、コードは何らかの方法で受信タスクを追跡する必要があります。 たとえば、次のコード スニペット:
コード
キャッシュ メカニズムは、スクリプトが 1 回のみリクエストできるようにする必要があります。キャッシュにすでに存在するかどうかは関係ありません。 したがって、キャッシュ システムがリクエストを正しく処理するには、最終的には、特定の URL にバインドされたコールバックを追跡するロジックを記述する必要があります。
ありがたいことに、これはまさにロジック遅延実装の一種なので、次のように実行できます:
コードをコピー
$.getScript( url ).then( defer.resolve, defer.reject );
}).promise();
}
return queuedScriptPromises[ url ].done( callback )
;
コードは非常に単純です。URL ごとに Promise オブジェクトをキャッシュします。 指定された URL に Promise がない場合は、遅延を作成してリクエストを行います。 すでに存在する場合は、コールバックをバインドするだけです。 このソリューションの大きな利点は、新しいリクエストとキャッシュされたリクエストを透過的に処理できることです。 もう 1 つの利点は、遅延ベースのキャッシュが障害状況を適切に処理することです。 Promise が「拒否」ステータスで終了した場合、テストするためのエラー コールバックを提供できます:
$.cachedGetScript( url ).then( successCallback, errorCallback );
覚えておいてください: いいえリクエストがキャッシュされているかどうかに関係なく、上記のコード スニペットは正常に動作します。
ユニバーサル非同期キャッシュ
コードを可能な限り一般化するために、キャッシュ ファクトリを構築し、実際に実行する必要があるタスクを抽象化します。
$.createCache = function( requestFunction ) {
var キャッシュ = {} ;
return function( key, callback ) {
if ( !cache[ key ] ) {
cache[ key ] = $.Deferred(function( defer ) {
requestFunction( 遅延、キー ) ;
}).promise();
キャッシュを返す
}
特定のリクエスト ロジックが抽象化されたので、cachedGetScript を書き直すことができます。
});
createCache を呼び出すたびに、新しいキャッシュ ライブラリが作成され、新しいキャッシュ取得関数が返されます。これで、キャッシュから値を取得する論理シナリオを簡単に実装できる汎用キャッシュ ファクトリが完成しました。
画像の読み込み
もう 1 つの候補シナリオは画像の読み込みです。同じ画像を 2 回読み込まないようにしてください。画像の読み込みが必要になる場合があります。 createCache を使用すると簡単に実装できます:
function cleanUp() {
image.onload = image.onerror = null;
}
defer.then( cleanUp, cleanUp );
image.onload = function() {
defer.resolve( url );
image.onerror = defer.reject; 🎜>image.src = url;
});
次のコード スニペットは次のとおりです:
コードをコピーします
image.png がロードされているか、ロード中であるかに関係なく、キャッシュは正常に機能します。ロードされています。
API レスポンスのキャッシュ データ
ページのライフサイクルを通じて不変とみなされている API リクエストも、キャッシュの最適な候補です。 たとえば、次の操作を実行します。
コードをコピーします
成功: defer.resolve,
エラー: defer.reject
});
プログラム キャッシュしながら Twitter で検索を実行できます:
タイミング
遅延ベースのキャッシュはネットワーク リクエストに限定されず、タイミング目的にも使用できます。
たとえば、気づきにくい特定の機能にユーザーの注意を引いたり、遅延の問題に対処したりするために、Web ページ上で一定の時間が経過した後にアクションを実行する必要がある場合があります。 setTimeout はほとんどのユースケースに適していますが、タイマーが起動した後、または理論的には期限切れになった後は解決策がありません。 次のキャッシュ システムを使用してこれを処理できます:
varreadyTime ;
$(function() {readyTime = jQuery.now(); });
$.afterDOMReady = $.createCache(function( defer, late ) {
lay = 遅延 | | 0;
$(function() {
var delta = $.now() - readyTime;
if ( delta >= 遅延 ) { defer.resolve(); }
else {
setTimeout ( defer.resolve, late - delta );
}
});
複数のアニメーションを同期する アニメーションは、非同期タスクのもう 1 つの一般的な例です。 ただし、無関係なアニメーションがいくつか完了した後にコードを実行するのは、まだ少し困難です。アニメーション要素の Promise オブジェクトを取得する機能は jQuery 1.6 でのみ提供されていますが、手動で簡単に実装できます:
var elements = this;
return $.Deferred(function ( defer ) {
elements.animate( prop, Speed, easing, function() {
defer.resolve();
if ( callback ) {
callback.apply( this, argument );
}
});
});
};
fadeDiv2In = $( "#div1" ).animatePromise({ opacity: 1 }, "fast" ); when( fadeDiv1Out, fadeDiv2In ).done(function() {
/* 両方のアニメーションが終了しました */
});
同じトリックを使用して、補助メソッド:
var 要素 = this;
return $.Deferred(function( defer ) {
要素[名前]( 速度, イージング, function() {
defer.resolve( );
if (コールバック) {
callback.apply(
}
}); ;
});
次に、次のように新しいヘルパー コードを使用してアニメーションを同期します。
コードをコピー
$.when(
たとえば、最初にクリックされたときにパネルを開き、パネルが開いた後に特定の初期化ロジックを実行するボタンが必要な場合があります。 この状況に対処するとき、人々は通常次のようなコードを書きます:
コードをコピー
コードは次のとおりです:
var buttonClicked = false;
$( "#myButton" ).click(function() {
if ( !buttonClicked ) {
buttonClicked = true;
コードをコピー
コードは次のとおりです:
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 を返します
コードは冗長ですが、関連する問題の処理が簡素化されます。 まずヘルパー メソッドを定義しましょう:
次に、ロジックは次のように再構築できます:
パネルが開いた後、必要なのはこれだけです:
コードをコピーします
パネルが開いていない場合、アクションはボタンがクリックされるまで遅延されます。
上記の例を個別に見てみると、promise の役割は限られています。 ただし、約束の本当の力は、それらを組み合わせることにあります。
パネルのコンテンツをロードし、最初のクリックでパネルを開きます
パネルを開き、そのコンテンツをリクエストしてからコンテンツをフェードインするボタンがあるとします。前に定義したヘルパー メソッドを使用すると、これを行うことができます:
コードをコピーします
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.

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











モバイル デバイスの普及に伴い、Web デザインでは、優れたユーザー エクスペリエンスを実現するために、デバイスの解像度やさまざまな端末の画面サイズなどの要素を考慮する必要があります。 Web サイトのレスポンシブ デザインを実装する場合、画像カルーセル効果を使用して限られた視覚ウィンドウに複数の画像のコンテンツを表示することが必要になることがよくありますが、同時に Web サイトの視覚効果も高めることができます。この記事では、CSS を使用してレスポンシブ画像の自動カルーセル効果を実現する方法を紹介し、コード例と分析を示します。実装のアイデア レスポンシブ画像カルーセルの実装は、CSS フレックス レイアウトを通じて実装できます。存在する

CSS を使用してレスポンシブなスライド メニューを実装するチュートリアルには、特定のコード サンプルが必要です。現代の Web デザインでは、レスポンシブ デザインは必須のスキルとなっています。さまざまなデバイスや画面サイズに対応するには、Web サイトに応答性の高いメニューを追加する必要があります。今日は、CSS を使用して応答性の高いスライド メニューを実装し、具体的なコード例を示します。まず、実装を見てみましょう。画面幅が一定のしきい値より小さい場合は自動的に折りたたまれ、メニューボタンをクリックすると展開するナビゲーションバーを作成します。

HTML、CSS、jQuery を使用してレスポンシブ タグ クラウドを作成する方法 タグ クラウドは、さまざまなキーワードやタグを表示するために使用される一般的な Web 要素です。通常、キーワードの重要性がさまざまなフォント サイズまたは色で表示されます。この記事では、HTML、CSS、jQueryを使ってレスポンシブタグクラウドを作成する方法と、具体的なコード例を紹介します。 HTML 構造の作成 まず、HTML でタグ クラウドの基本構造を作成する必要があります。順序なしリストを使用してタグを表すことができます

日常生活では、約束と履行の間で問題に遭遇することがよくあります。個人的な関係でもビジネス取引でも、約束を守ることが信頼を築く鍵となります。ただし、コミットメントの是非についてはしばしば議論の余地があります。この記事では、約束の長所と短所を検討し、約束を守る方法についていくつかのアドバイスを提供します。約束されたメリットは明らかです。まず、コミットメントは信頼を築きます。人が約束を守るとき、その人は信頼できる人であると他人に信じ込ませます。信頼は人々の間に確立される絆であり、それは人々をより良くすることができます

HTML と CSS を使用してレスポンシブなカルーセル レイアウトを作成する方法 カルーセルは、最新の Web デザインの一般的な要素です。ユーザーの注意を引いたり、複数のコンテンツや画像を表示したり、自動的に切り替えたりすることができます。この記事では、HTMLとCSSを使ってレスポンシブカルーセルレイアウトを作成する方法を紹介します。まず、基本的な HTML 構造を作成し、必要な CSS スタイルを追加する必要があります。以下は単純な HTML 構造です: <!DOCTYPEhtml&g

HTML、CSS、jQuery を使用して応答性の高いスクロール通知バーを作成する方法 モバイル デバイスの普及と、Web サイトへのアクセス エクスペリエンスに対するユーザーの要件の増加に伴い、応答性の高いスクロール通知バーの設計がますます重要になっています。レスポンシブ デザインにより、Web サイトがさまざまなデバイスで適切に表示され、ユーザーが通知コンテンツを簡単に表示できるようになります。この記事では、HTML、CSS、jQuery を使用して応答性の高いスクロール通知バーを作成する方法を紹介し、具体的なコード例を示します。まず、HTM を作成する必要があります

Layui を使用してレスポンシブなカレンダー機能を実装する方法 1. はじめに Web 開発において、カレンダー機能は一般的な要件の 1 つです。 Layui は、カレンダー コンポーネントを含む豊富な UI コンポーネントを提供する優れたフロントエンド フレームワークです。この記事では、Layuiを使ってレスポンシブカレンダー機能を実装する方法と具体的なコード例を紹介します。 2. HTML 構造 カレンダー機能を実装するには、まず適切な HTML 構造を作成する必要があります。 div 要素を最も外側のコンテナとして使用し、その中で使用できます。

HTML と CSS を使用して応答性の高い音楽プレーヤー ページ レイアウトを作成する方法 インターネットの発展により、音楽プレーヤーは人々の生活に欠かせないものになりました。優れた音楽プレーヤー ページ レイアウトを作成する場合、HTML と CSS は不可欠なツールです。この記事では、HTML と CSS を使用してレスポンシブな音楽プレーヤー ページ レイアウトを作成する方法と、具体的なコード例を紹介します。ページ構造 まず、HTML ドキュメントを作成し、ページの基本構造を定義する必要があります。以下は概要です
