モバイルWeb app開発必須-非同期キューDeferred
13265 ワード
背景
モバイルWeb appの開発では、非同期コードはよくあることです.例えば、一般的な非同期操作があります. Ajax(XMLHttpRequest) Image Tag,Script Tag,iframe(原理類似) setTimeout/setInterval CSS3 Transition/Animation HTML5 Web Database postMessage Web Workers Web Sockets and more…
後のいくつかはCSS 3 HML 5が加入した新しいAPIである.これらのインタフェースは非同期の操作を生成します
例えば、本人のphonegapプロジェクトでは、HTML 5のローカルデータベース(HTML 5 Webデータベース)を操作するのは非同期のプロセスであり、複数のクエリーを同時に実行する場合、同期コードはデータクエリーが終了した後に呼び出されるのを待つ必要があります.
添付ソース:複数の非同期クエリーを実行する
コードの整理方法
しかし、非同期+コールバックのモードでは、一連の非同期操作をフロー制御する必要がある場合、必ずコールバックネストに直面するようです.そのため、どのように非同期操作を「平らにする」のか、より良い方法で非同期プログラミングの体験を最適化し、同時により丈夫な非同期コードを書くのかは、この2年間、フロントエンドの輪の中で人気のある話題だ.
代表的メッセージドライバ-@朴霊を表すEventProxy . Promiseモード-代表:CommonJS Promises2jQuery2Dojo 二次コンパイル-代表:@趙さんのJscex jQueryはこのwhenメソッドを実装した唯一のライブラリである.他のpromisesライブラリ、例えばQ、Dojo、およびwhenは、Promises/B specに従ってwhenメソッドを実装したが、注釈者が言及したwhenメソッドは実装されなかった.しかし、Qライブラリにはallメソッド、whenがあります.jsにもparallelメソッドがあり、上のjQueryとwhenメソッドは、任意の数のパラメータではなく、配列タイプのパラメータを受け入れるだけで機能します.
Jquery Deferredのレビューは1.5バージョンから、jQueryにDeferred機能が追加され、イベント処理キューがより充実しています.このメカニズムでAjaxモジュールを書き換えました.まだAjaxの番になっていませんが、次のイベント処理関数ではこのメカニズム に関連しています. Deferredはコールバック関数を1つのキューに登録し、統一的に管理し、これらの関数を同期または非同期で呼び出すことができる.jQuery.Deferred()は、Deferredオブジェクトを作成するために使用されます.オブジェクトには状態値があり、Rejected、Resolved、初期状態の3種類があります.ここでResolvedは操作が正常に完了したことを示し、Rejectedはエラーが発生し、呼び出しに失敗したことを示します.Deferredオブジェクトの主なメンバーは次のとおりです: done(callback):resolved状態で呼び出されるcallback関数を登録します. fail(callback):ステータスがrejectedの場合に呼び出されるcallback関数を登録します. always(callback):resolvedまたはrejectedにかかわらず呼び出されるcallback関数を登録します. then(successCallback,failureCallback):成功と失敗のコールバック関数を同時に入力します. pipe(successFilter,failureFilter):正常および失敗したコールバック関数を呼び出す前に、pipeによって指定された関数を呼び出す.関数呼び出しをブロックするパイプメカニズムです. resolve(args):ステータスをResolvedに設定します. reject(args):ステータスをRejectedに設定します. promse():resolveとrejectがない不完全なDeferredインタフェースを返します.つまり、Deferredオブジェクトの状態は変更できません.読み取り専用ビューと見なすことができます.これは、外部関数がコールバック関数を早期にトリガーしないようにするためです.例えば$ajaxは、バージョン1.5以降、XMLHttpRequestではなく、XMLHttpRequestとDeferredオブジェクトインタフェースがカプセル化されたobjectを返します.ここでDeferred部分はpromise()で得られ,外部関数にresolveとrejectを呼び出させずajaxが完了する前にコールバック関数をトリガすることを防止する.この2つの関数の呼び出し権限をajax内部に保持します.
deferred-js
本人はプロジェクトの中でPromise/A規範で実現したdeferred-jsを使って、比較的に簡単で軽量である.
使用方法
API:
最も簡単によく使われるケース
各リンクは、1つのコールバックチェーンで2つの関数であり、1つの成功、1つの失敗を表すことができます.
成功したコールバックは1つしかありません
失敗コールバック
成功メソッドと失敗メソッドの追加
コールバックが成功しても失敗しても同じコードを実行します.
提供されるケースなど、多くの非同期が操作されている場合、HTML 5データベースをN回実行した後、どのように操作しますか?
次のケースの
allのメソッドは、すべての遅延キューのロードが完了するのを待ってから、後続のコードを実行します.
使いやすいし、シンプルで複雑な概念はありません
チュートリアルの使用後、次のセクションのソースコードの実装
モバイルWeb appの開発では、非同期コードはよくあることです.例えば、一般的な非同期操作があります.
後のいくつかはCSS 3 HML 5が加入した新しいAPIである.これらのインタフェースは非同期の操作を生成します
例えば、本人のphonegapプロジェクトでは、HTML 5のローカルデータベース(HTML 5 Webデータベース)を操作するのは非同期のプロセスであり、複数のクエリーを同時に実行する場合、同期コードはデータクエリーが終了した後に呼び出されるのを待つ必要があります.
添付ソース:複数の非同期クエリーを実行する
/**
*
* @return
*/
proto.initProcess = function(){
var self = this,
prev = null ,
curr = null ,
next = null ;
debug.group("start of init process");
var idx = self.chapterIndex;
debug.info("PageBase: !");
self.initProcessBefore();
if(idx == 0){
debug.info("PageBase: ");
debug.info("PageBase: !");
curr = self.process(self.chapters[idx]);
curr.then(function(pages){
debug.info(self.format("PageBase: , {0}" , pages.length));
self.cPages = pages;
if(self.isChangeFont){
self.idx = Math.ceil((pages.length - 1) * self.idx);
}
self.cPages.idx = idx;
/////////////////////////////////////////////////
//
// 2013.1.10
//
//
if(1 === self.chapters.length){
deferred.all([curr]).then(self.steup.bind(self));
}else{
debug.info("PageBase: !");
next = self.loadNextData(idx + 1);
next.then(function(args){
debug.info(self.format("PageBase: , {0}" , args.pages.length));
self.nPages = args.pages;
self.nPages.idx = idx + args.index;
debug.info(self.format("PageBase: , {0} {1} {2} {3}"
, self.cPages.idx , self.cPages.length , self.nPages.idx , self.nPages.length));
debug.info("PageBase: , !");
});
deferred.all([curr , next]).then(self.steup.bind(self));
}
});
}else if(idx == self.chapters.length -1){
debug.info("PageBase: ");
debug.info("PageBase: !");
prev = self.loadPrevData(idx - 1);
prev.then(function(args){
self.pPages = args.pages;
self.pPages.idx = args.index + 1;
debug.info(self.format("PageBase: , {0}" , args.pages.length));
curr = self.process(self.chapters[idx]);
curr.then(function(pages , data){
if(self.isChangeFont){
self.idx = Math.ceil((pages.length - 1) * self.idx);
}
self.cPages = pages ;
self.cPages.idx = idx;
debug.info(self.format("PageBase: , {0}" , pages.length));
debug.info(self.format("PageBase: , {0} {1} {2} {3} "
, self.pPages.idx , self.pPages.length , self.cPages.idx , self.cPages.length ));
debug.info("PageBase: , !");
});
deferred.all([prev , curr]).then(self.steup.bind(self));
});
}else{
debug.info("PageBase: ");
prev = self.loadPrevData(idx - 1);
debug.info("PageBase: !");
prev.then(function(args){
self.pPages = args.pages ;
self.pPages.idx = args.index;
debug.info(self.format("PageBase: , {0}" , args.pages.length));
debug.info("PageBase: !");
curr = self.process(self.chapters[idx]);
curr.then(function(pages , data){
if(self.isChangeFont){
self.idx = Math.ceil((pages.length) * self.idx);
// console.log("spages.length - 1",pages.length)
// console.log("self.idx",self.idx)
}
self.cPages = pages ;
self.cPages.idx = idx;
debug.info(self.format("PageBase: , {0}" ,pages.length));
debug.info("PageBase: !");
next = self.loadNextData(idx + 1);
next.then(function(args){
self.nPages = args.pages ;
self.nPages.idx = idx + args.index;
debug.info(self.format("PageBase: , {0}" , args.pages.length));
debug.info(self.format("PageBase: , {0} {1} {2} {3} {4} {5}"
, self.pPages.idx , self.pPages.length , self.cPages.idx , self.cPages.length , self.nPages.idx , self.nPages.length));
debug.info("PageBase: , !")
});
deferred.all([prev , curr , next]).then(self.steup.bind(self));
});
});
}
コードの整理方法
しかし、非同期+コールバックのモードでは、一連の非同期操作をフロー制御する必要がある場合、必ずコールバックネストに直面するようです.そのため、どのように非同期操作を「平らにする」のか、より良い方法で非同期プログラミングの体験を最適化し、同時により丈夫な非同期コードを書くのかは、この2年間、フロントエンドの輪の中で人気のある話題だ.
代表的
Jquery Deferredのレビュー
deferred-js
本人はプロジェクトの中でPromise/A規範で実現したdeferred-jsを使って、比較的に簡単で軽量である.
使用方法
API:
var DeferredAPI = {
deferred : deferred,
all : all,
Deferred : Deferred,
DeferredList : DeferredList,
wrapResult : wrapResult,
wrapFailure : wrapFailure,
Failure : Failure
}
最も簡単によく使われるケース
//Deferred
var d = new deferred.Deferred()
//
d.then(function(result) {
console.log('Hello ' + result)
return result
})
//
d.resolve('World')
各リンクは、1つのコールバックチェーンで2つの関数であり、1つの成功、1つの失敗を表すことができます.
成功したコールバックは1つしかありません
d.then(function(result) {
//
return result
})
失敗コールバック
d.fail(function(failure) {
// optionally do something useful with failure.value()
return failure
});
成功メソッドと失敗メソッドの追加
d.then(function(result) {
// do something useful with the result
return result
}, function(failure) {
// optionally do something useful with failure.value()
return failure
})
コールバックが成功しても失敗しても同じコードを実行します.
d.both(function(result) {
// in the case of failure, result is a Failure
// do something in either case
return result
})
提供されるケースなど、多くの非同期が操作されている場合、HTML 5データベースをN回実行した後、どのように操作しますか?
次のケースの
deferred.all([prev , curr , next]).then(self.steup.bind(self));
allのメソッドは、すべての遅延キューのロードが完了するのを待ってから、後続のコードを実行します.
使いやすいし、シンプルで複雑な概念はありません
チュートリアルの使用後、次のセクションのソースコードの実装