JS非同期キューの実装

20119 ワード

これは比較的深い話題かもしれません.非同期とは?
要約すると、非同期はjavascriptで遅延実行である.厳密に言えば、javascriptの非同期プログラミング能力は、settimout、XMLhttpRequest、DOMのイベントメカニズム、HTML 5で新たに増加したwebwork、postMessageなど、BOMとDOMによって提供されています.これらのものには共通の特徴があり、コールバック関数を持ち、制御反転を実現することです.制御反転はより奥深い問題であるため,ここでは展開したくない.しかし、コールバック関数の存在が元の実行プロセスを遮断し、適切なタイミングで自動的に現れて実行させることが確認できます.これは非常に便利なモードです.アクティブなポーリングと比較して、どれだけ省エネかがわかります.同期プログラミングでは、コードは基本的に上から下へ実行され、非同期プログラミングでは、いくつかのコードがコールバック関数に書き込まれます.コード間に依存がある場合、コールバック関数のコールバック関数をセットする場合も珍しくありません.このようなセット構造は、今後のメンテナンスにとって地獄です.もう一つ直面しなければならない状況がありますtry...catchは数ミリ秒後に発生した異常をキャプチャできません.また、settimeoutに加えて、非同期プログラミングは基本的にイベントメカニズムによって負担され、それらのコールバック関数がいつ発生するかは基本的に未知数であり、バックグラウンドでシステムレベルのエラーが発生したため、応答を出すことができない可能性があります.あるいは、システムが忙しくて、一時的に応答できません.この2つの状況についても、この操作を中断する戦略を提供する必要があります.すなわちabortとは,これらが非同期プログラミングの課題である.

  
   
   
   
   
$.post( " /foo.json " , function (dataOfFoo) { // Ajax
$.post( " /bar.json " , function (dataOfBar) {
$.post(
" /baz.json " , function (dataOfBaz) {
alert([dataOfFoo, dataOfBar, dataOfBaz]);
});
});
});

function throwError(){
throw new Error( ' ERROR ' );
}

try {
setTimeout(throwError,
3000 );
}
catch (e){
alert(e);
//
}

Javascriptプログラミングでは,いつでもこのようなニーズに直面するため,関連する軽快なAPIを実現することが重要である.前述したように、コールバック関数のセット(domReary、マルチキャストイベント、特効)を格納し、特定の時点ですべてのコールバック関数を実行し、エラーが発生したら対応する処理関数(負のコールバック)をトリガーし、操作全体を中止し、中断から操作を再開することができ、より多くの要求があればシリアルからパラレルに移行したいと考えています.パラレルからシリアルに移行します.多くの概念が分からないのではないでしょうか.しかし、良い特効を得るには、これらが必要です.もしJSを遊んだ人がいたら、きっとnodeを聞いたことがあるに違いない.jsは、今では基本的にその代名詞になっています.ルート配布、IO操作、すべて非同期で、イベント駆動で、優雅な非同期プログラミングを実現するために、大牛たちは忙しくて頭がぼうっとして、do.js. step.js, async.js, flow.js......、あまり鶏の肋骨ではなく、先端に適用できません.そのため、フロントエンドに適した案が必要です.
あなたが考えていることは、すでに研究されており、解決策が与えられていることを理解しなければなりません.10大javascriptフレームワークの一つ、Mochikitは、PythonのTwistedライブラリからDeferredを手に入れ、その後dojoに学んだが、今では同じものがjQuery 1に現れているのを見ている.5に上がりました.しかし、MochikitのDeferredにはもう一つの知られていない分岐点があり、日本の大牛cho 45が作った(彼はBigIntも何をしているのか、ブラウザをまたいでTestingをしている.有名なのはamachang、uuupaa、edvakf、nantoに続いている).JSDDeferredと呼ばれている.まずdojoの派閥の(jQueryを含む)Deferredは、ずっと無敵状態で、Commonと.jsは1セットの規範を作り出して、どんなpromises、then、whenはすべてその時制定して、jQuerは基本的に全面的に受け入れます.もう一つのブランチ、cho 45のJSDeferredは、配列を使用してコールバック関数をロードするのではなく、settimout、imageを使用するという奇抜な発想です.onload、postMessageなどの非同期メカニズムは巧みにメンテナンス列の作業道をブラウザ自身に戻し、致命的な欠陥があるが、その使いやすさも日本のJS界に認められ、私のDeferredオブジェクトはその基本的な発展から来ている.Deferredというものは、私は通常非同期列と呼ばれています.それは確かにコールバックの手紙で構成された2つの列が必要で、非常にイメージされています.
非同期キューを移動する前に、通常のキューがどのように遅延しているかを見てみましょう.

  
   
   
   
   
var Queue = function (){
this .list = []
}
Queue.prototype
= {
constructor:Queue,
queue:
function (fn) {
this .list.push(fn)
return this ;
},
dequeue:
function (){
var fn = this .list.shift() || function (){};
fn.call(
this )
}
}

このように呼び出します.

  
   
   
   
   
var q = new Queue;
q.queue(
function (){
log(
1 )
}).queue(
function (){
log(
2 )
}).queue(
function (){
log(
3 )
});
while (q.list.length){
q.dequeune();
}

しかし、これは同期であり、非同期にするにはsettimeoutを使用する必要があります.

  
   
   
   
   
var el = document.getElementById( " test " );
var q = new Queue();
q.queue(
function (){
var self = this ;
el.innerHTML
= 1
setTimeout(
function (){
self.dequeue()
},
1000 );
}).queue(
function (){
var self = this ;
el.innerHTML
= 2
setTimeout(
function (){
self.dequeue()
},
1000 );
}).queue(
function (){
var self = this ;
el.innerHTML
= 3
setTimeout(
function (){
self.dequeue()
},
1000 );
}).dequeue()

皆さんがご覧のように、このように書くのは絶対に友好的ではありません.私たちはsettimeoutをQueueクラスに整理し、queueをいくつか修正する必要があります.1つの関数だけをポップアップして実行しないでください.通常、domReay、マルチ投票イベントなど、列のすべてのコールバックを操作します.

  
   
   
   
   
var Queue = function (){
this .list = []
}
Queue.prototype
= {
constructor:Queue,
queue:
function (fn) {
this .list.push(fn)
return this ;
},
wait:
function (ms){
this .list.push(ms)
return this ;
},
dequeue:
function (){
var self = this , list = self.list;
var el = list.shift() || function (){};
if ( typeof el == " number " ){
setTimeout(
function (){
self.dequeue();
},el);
}
else if ( typeof el == " function " ) {
el.call(
this )
if (list.length)
self.dequeue();
}
}
}

Greatは,各コールバックの間隔を自由に制御できれば,アニメーション効果として非常に簡単になる.しかし、このQueueクラスは私たちが最初に定めた目標に比べて、まだ遠いです.Ajax、マルチキャストイベント、domReayはすべてその支配下に帰属するので、より適用性の高いAPIを使用する必要があります.dojoを使ったことがある人も知っているように、そのDeferredはDNAの染色体のように二重線で、同じ時間線にない異常を捉えることができ、しかもこれらの列は衛生箸のように一度使って廃棄することができず、多投事件の実現を支えることができない.これらの機能を実現するには、複雑なものが必要です.私は第2部で私の非同期列を盛大に紹介し、これらの問題をどのように優雅に解決するかを見ます.