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.

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

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

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

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

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。
