雄弁なJavaScriptの#15#非同期プログラミング(渣翻)

//廃棄物を削除

 

1同期、非同期VS.

ほとんど知っている説明を参照してください。

アナロジー。あなたは、書店の図書館、書店に行くと何もありませんボス尋ねた「完全なコードを。」

プロセスが同期である場合、上司は言うだろう:「あなたはまだここに立って、私は検索のために行きます。」だからカウンターで、ああ、ボスが再び表示され、あなたに結果を伝えるまで、ああ。非同期のアプローチは、上司は、あなたが幸せに(?)家に帰るために、あなたを呼び出すちょっと待って、私はああ見つけてみましょう、あなたを教えています... 

 

2、カラス技術
多くの人々はカラスが特にスマート鳥であることを知っています。彼らは、事前に計画するためのツールを使う事を覚え、さらには相互に通信することができます。
しかし、ほとんどの人は、それは、彼らが我々が知らない機能の多くを非表示にすることであるか分かりません。私は非常に評判の良い専門家はカラス科、カラスの技術は非常に遠く離れて人間からではない言うのを聞いた、と彼らは追い上げています。
例えば、多くのカラスの文明は、コンピューティングデバイスを構築する能力を持っています。これらのデバイスは、人間の電子コンピューティングデバイスとは異なりますが、小さな昆虫の行動を介して動作、これらの昆虫は、シロアリの種に密接に関連して、カラス、彼らは共生関係を形成します。クロウは、見返りに、彼らのために昆虫を食料を提供し、その内部の生活の助けを借りて計算され、複雑なコロニーを、構築するためにそれらを操作します。
これらのコロニーは、通常、大きな位置し、カラスの巣では長い時間があります。カラスや昆虫が枝の間に隠れ、球状粘土構造のネットワークを構築するために一緒に働くには、カラスの巣、昆虫を構成し、それが生活や仕事にここにあります。
これらのマシンは、光通信信号と他の機器を使用します。反射材料は、特別なカラス通信ロッドに埋め込まれている、他の巣に光を反射し、これらの昆虫材料は、迅速にフラッシュの系列にデータを符号化します。
私たちの友人は、カラス科の専門家は、Rhの?ネ川HièresシュルAmby村は、巣のネットワーク展開図をカラス描かれています。このマップは、巣との接続を示しています。
この例では、JavaScriptを実行できる衝撃的な融合の進展、カラスコンピュータ。この章では、我々は彼らにいくつかの基本的なネットワーク機能を記述します。

 

図3に示すように、コールバック関数
コールバック関数-非同期プログラミング機能の方法は、ジョグ動作は、追加のパラメータを受信し実行することです。遅い動作が終了すると、コールバック関数を呼び出します(引数として結果)。
例えば、Node.jsの及びブラウザで(1秒は1000ミリ秒である)のミリ秒の所定の数を待って、利用可能なsetTimeout関数であり、その関数を呼び出します。

setTimeout(()=>はconsole.log( "ティック")、500)。

待ちは通常、非常に重要な仕事ではありませんが、実行中に、このようなアニメーションを更新するように、それは有用である可能性がある特定のタスクが与えられた時間を超えて費やした時間を確認してください。

連続転送では、新しい操作コールバック関数の非同期操作を処理する必要があることを意味した後、後続の計算を複数連続して行います。
ほとんどのコンピュータは、永続的なデータのためにカラスの巣ランプを持って、情報が枝にエッチングされ、そのためには、後で検索することができます。エッチング又は取得データは、いくつかの時間がかかるので、データ記憶のために、検索インタフェースは、非同期であり、コールバック関数が必要。
エンコードされたJSONによってランプの名前に基づいて、永続データを格納します。クロウパック情報配列の実際の名前を記述するためにキャッシュされたデータポイントを含めることができます名前「食品キャッシュ」、下に隠された食品の場所。ビッグオーク電球(大オーク)カラスの巣食品キャッシュを持続見つけるには、カラスは、次のコードを実行することができます。

"./crow-tech"からインポート{bigOak} 

bigOak.readStorage( "フード・キャッシュ"、キャッシュ=> { 
  せfirstCache =キャッシュ[0 ]; 
  bigOak.readStorage(firstCache、情報 => { 
    にconsole.log(情報); 
  }); 
});

(すべての名前と結合文字列がクロウ語から英語に翻訳されています。)
各インデントレベルは、非同期操作(コールバック関数本体になりますと、このスタイルのプログラミングが可能ですが、最終的に別の関数を入力しますので、 ?)が増加します。このように同時に複数のアクションを実行しているなど、より複雑なものを、実行し、それはあなたが少しぎこちない感じさせることがあります。
クロウズネストのコンピュータが要求を使用しています-通信に対応して。これは、カラスの巣は、別のクロウズネストにメッセージを送信することを意味し、クロウズネストは、応答メッセージ、確認メッセージが受信された直後に別のメッセージを受信し、メッセージに尋ねた質問への回答が含まれていてもよいです。
各メッセージは、メッセージが処理されるべきかを決定するタイプで標識されています。我々は、このような要求を受信した場合、それは対応するハンドラ(ハンドラ)が応答を生成するために呼び出す、コードハンドラ(ハンドラ)要求の特定のタイプを定義することができます。
コールバック・メカニズムに基づいて通信機能を提供するための「./crow-tech」エクスポートモジュールインターフェース。送信するための送信要求を使用してクロウ方法。ターゲットの巣、要求および方法の最初の3つのパラメータの要求のコンテンツタイプの名前を、それが最後のパラメータである(つまり、四番目のパラメータである)あなたが応答を受信したときに呼び出すコールバック関数を準備しています。

bigOak.send( "牛の牧場は"、 "のは午後7時大声CAWう"、 "注意" 
            () =>はconsole.log( "注配信"));

しかし、要求を受信することができカラスの巣を作るために、我々は最初の「ノート」と呼ばれる要求のタイプを、定義する必要があります。コンピューター上でカラスの巣で実行するだけではなく、要求を処理するだけでなく、すべてのカラスの巣で実行されるコードは、このようなメッセージを受け取ることができます。今、私たちは、カラスが飛んできているとし、そして私たちのハンドラのコードは、すべてのカラスの巣の上にインストールされています。

"./crow-tech"からインポート{defineRequestType} 

defineRequestType( "注意"(ネスト、コンテンツ、ソース、行わ)=> { 
  にconsole.log( `$ {nest.nameは}注受信; $ {内容}`) 
  ()を行います; 
});

defineRequestType関数は、要求の新しいタイプを定義します。この例では、要求の「ノート」のサポートを追加し、それだけ与えられたカラスの巣にメモを送信します。我々は、要求が到着したかどうかを確認できるように、私たちの実装では、にconsole.logと呼ばれます。クロウズネストは、name属性を持って、自分の名前を保存します。
4番目のパラメータがハンドラが呼び出されなければならないコールバック要求の完了時に行われます提供します。私たちは応答値としてハンドラの戻り値を使用する場合、これは要求ハンドラ(ハンドラ)自体は非同期で実行することができないことを意味します。この関数は非同期操作は通常の作業が完了する前に返し行い、それが非同期的に完了したときにコールバック関数を呼び出します。したがって、この場合には、我々はいくつかの非同期のメカニズムを必要とする-別のコールバック関数信号を応答が利用可能になったとき。
[ハンドラ自体は非同期の仕事、実装はハンドラ内で行われた後に呼び出され、別のコールバック関数で行われるコールバックハンドラである]
伝染非同期で。任意の関数自体を動作するように非同期関数呼び出しが結果を提供するために、コールバックまたは類似のメカニズムを使用して、非同期でなければなりません。コールバック関数は、エラーを単にやすいよりも値を返し、そのプログラムは非常に良いではありません、このようにコンテンツのほとんどを構築する必要があります。

 

4、約束
の抽象化を使用するには、通常は難しいことですが、これらの概念は、値で表現することができたときに、それが比較的容易になります。例えば、非同期操作の例では、あなたではなく、将来のある時点で配置された関数を呼び出すよりも、将来の事象のオブジェクト表現を返すことができると述べました。
我々は、標準クラスを約束する必要がある理由です。約束は非同期操作で、値が一度に完成された結果を生成することができます。その結果の値が利用可能な場合、それがこの結果の値に興味を持ってすべての人に知らせることができます。[いわゆる興味がある人は、実際には、パラメータとしてコールバック関数の結果を評価する必要性を指し]
最も簡単な方法は、Promise.resolve関数を呼び出すことである約束を作成します。この機能を使用すると、渡された値が約束に包まれていることを保証します。それはすでに約束された場合、それは単に返す-そう、あなたが新しい約束を取得します、約束はあなたが合格値の値の約束を作成し、その時点で終了し、その結果としてされています。

15 = Promise.resolveをしましょう(15 )。
fifteen.then(値 => はconsole.log( `ガット$ {値}`))。
// →ガット15

結果は、その値を約束する方法を用いて得ることができます。この必要性は、約束が完了すると、コールバック関数を渡す(または解決)、および結果値を生成するために、関数が呼び出されます。あなたは、単一の約束に複数のコールバックを追加し、あなたが(完了)約束を解決した後でも唯一まだそれらをトリガーするこれらのコールバックを追加することができます。
その後、この方法は、それよりもはるかに多くを行います。また約束さらに、その結果値はハンドラが約束を返した場合、その約束の完了を待つ、関数処理された値で返され、(継続して受け継が結果値として戻り値を解決することを約束を返します。その後、コールバック)。
理解を容易にするために、我々は、デバイス非同期世界に転送された値との約束を置くことができます。正常値はそこだけ何もありません。値の両方の約束をしていた可能性があり、それだけの時間で、将来の時点で表示されることがあります。約束の計算は、非同期包装さ値で実行されるアクションに応じて定義され、その結果値を得ます。
約束は約束のコンストラクタを使用して作成することができます。そのインターフェースは非常に奇妙である-コンストラクタは、引数としての機能を必要とし、それはすぐに機能が約束を完了するために使用できる関数を渡し、この関数を呼び出します。これは、例えば、代わりに解決方法を使用しての、プロミスコンストラクタの仕事なので、それだけを完了することを約束するコードを作成します。
メソッドを作成しreadStorage機能のためのインタフェース仕様を約束に準拠しています。

関数記憶装置(巣、名){
   戻り 、新たな約束(決意=> { 
    nest.readStorage(名前、結果 => 解決(結果); 
  }); 
} 

ストレージ(bigOak、 "敵" 
  .then(値 =>はconsole.log( "ガット"、値))。

この非同期関数は、意味のある値を返します。これは約束の最大の利点である - それは、非同期機能の使用を簡素化します。彼らは、入力パラメータとして使用され、その出力を返します:約束は、より従来の機能のように見えるにコールバック関数を渡すために継続して反対をベースにしています。唯一の違いは、出力はすぐにではないかもしれないということです。

 

5、失敗

例外がスローされることがありますjsの従来のプログラミングは、非同期操作は例外をスローすることも可能ですが、またに対処するのは非常に難しいです。

広く用いられている方法は、異常情報を受信するために、コールバック関数を使用することです。

// (ブーリアン、OBJ)→未定義の
関数コールバック(成功、データ、 / * 他の引数.. * / ){
     // このようなコールバック関数は、常に、それらが例外を受信したか否かをチェックしなければなりません
    
}

約束はこれです:

新しい約束((_、拒否)=>(拒否新しいエラー( "失敗" )))
  .then(値 =>はconsole.log( "ハンドラ1" )) キャッチ(理由=> { 
    にconsole.log( "キャッチ失敗" + 理由);
     戻り "ナッシング" ; 
  })
  .then(値 =>はconsole.log( "ハンドラ2" 値))。
// →キャッチ失敗エラー:失敗
// →ハンドラ2は何も

 

6、ネットワークが難しいです

コールバック関数を表現することができる何かが、約束も表現できなければなりません。

ネットワーク環境は、事故に非常に傾向があるので、必要に応じて適切なタイムアウトを設定するための要求方法、遅延が何とかハングアップするために応答を受信できないため、それ以外のプログラムが可能です。

クラスタイムアウトエラー{}延び

機能要求(巣、ターゲット、タイプ、コンテンツ){
   戻り 、新たな約束((決意、リジェクト)=> { 
    せ行わ = 偽を関数試行(N){ 
      nest.send(ターゲット、タイプ、コンテンツ、(失敗、値) => { 
        行わ = ;
         場合(失敗)リジェクト(失敗);
         他の解決(値); 
      }); 
      のsetTimeout(() => {
         場合(行う)戻りそうでない 場合(N <3)試行(N + 1 )。
        他の拒否(新しいタイムアウト(「時限アウト」)); 
      }、 250 )。
    } 
    試み( 1 )。
  }); 
}

非同期再帰ループ必見の構築!上記の例では。送信したsetTimeoutは非同期である、サイクリングは、非同期関数によるものではなく、停止しました。

適切な要求ハンドラ:

関数requestType(名前、ハンドラ){ 
  defineRequestType(名前、(巣、コンテンツ、ソース、
                           コールバック) => {
     試みる{ 
      Promise.resolve(ハンドラ(巣、コンテンツ、ソース))
        .then(応答 =>コールバック(NULL 、応答)、
              故障 => コールバック(故障)); 
    } キャッチ(例外){ 
      コールバック(例外); 
    } 
  })。
}

 

約束の7、コレクション

Promise.all:

requestType( "ピング"、()=> "ピンポン" )。

関数availableNeighbors(ネスト){ 
  要求せ = nest.neighbors.map(隣接=> {
     リターン要求(巣、隣人、 "ピング" 
      .then(() => trueを、()=> ); 
  }); 
  戻り .then Promise.all(リクエスト)(結果=> {
     戻り nest.neighbors.filter((_、I)=>の結果、[I]); 
  }); 
}

 

8、ネットワーク洪水

「./crow-tech」からインポート{どこでも} 

どこでも(ネスト => { 
  nest.state.gossip = []; 
}); 

関数 sendGossip(巣、メッセージ、exceptFor = NULL ){ 
  nest.state.gossip.push(メッセージ)。
  (nest.neighborsの隣人をしましょう){
     場合(隣人== exceptFor)続けます
    要求(巣、隣人、「ゴシップ」、メッセージ)。
  } 
} 

requestType( "ゴシップ"、(巣、メッセージ、ソース)=> {
   場合(nest.state.gossip.includes(メッセージ))リターン ;
  console.log( `$ {nest.nameは}ゴシップ受信 ' $ { 
               メッセージ} ' $ {ソース}`から)。
  sendGossip(巣、メッセージ、ソース)
});

おすすめ

転載: www.cnblogs.com/xkxf/p/9587814.html