Javascriptの非同期調査

入門

  • 同期タスク:のみ最初のタスクが完了し、あなたが後にタスクを実行することができ、タスクの実行のメインスレッドに並びます。
  • 非同期タスクは:タスクキューのタスクに、タスクキューは、非同期タスクを行うことができ、メインスレッドに通知し、このタスクは、メインスレッドに入り、メインスレッドを入力しないでください。

方法:

  1. コールバックコールバック
  2. 約束の約束
  3. 非同期/のawait

1.コールバック

Node.jsの最古の直接非同期プログラミングの概念は、コールバックで反映しています。その形はB、Bが登録する最後のパラメータAを書面で入れてコールバック関数として登録されています。登録タスクAが完了した後、Bが呼び出されます。我々は、ファイルの読み込みが完了した後で、一方、他のコマンドを実行し、ファイルを読むことができますしながら、例えば、我々は、引数のコールバック関数の戻りとして内容を提出します。NOの場合、実行コードやファイルI / O操作を待ってブロックされているので。これは、大幅にパフォーマンスが向上し、同時多数の要求を処理することができます。

欠点は、この構文は、各タスクにのみコールバック関数を指定することができるということです複数の非同期操作のための需要があるのであれば、過去に、あなたは、操作の数に連続した非同期操作の間待つ必要があり、次の操作の終了を行い、次のコードでは)また、コールバック地獄と呼ばれる:(表示されます

getData(a => {
  getMoreData(a, b => {
    getMoreData(b, c => {
      getMoreData(c, d => {
        getMoreData(d, e => {
          console.log(e);
        })
      })
    })
  })
})

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

2.Promise /その後、

この問題を解決するために、のECMAScript 6プロミス・コンセプトを提供します。

約束はオブジェクトであり、非同期動作を表す(将来の事象の代わりに起こる)、ならびにその実行状態のは、コンストラクタの約束を見てみましょう。

new Promise( function(resolve, reject) {...} /* executor */  );

Promise引数コンストラクタは、我々はエグゼキュータ彼を呼び出す機能です。エグゼキュータとresolveし、reject二つのパラメータ、これらのパラメータは、パラメータ値のそれぞれ、各機能カテゴリが約束でもあります。次のようにプロトタイプは次のようになります。

Promise.resolve(value)
Promise.reject(value)

まず言及し、Promise3つのがある初始(pending)``、完成(fulfilled)状態が:失败(rejected)、。

新しい約束は、コードがあるとき:一部の非同期操作を行い、その後、最終的に呼び出すresolveと、reject二つのうちの一つ。非同期タスクとリターンが正常に完了した、と呼ばれるべきである場合にはresolve、障害の原因(通常はエラーオブジェクト)で失敗しました時に、非同期タスクは、呼び出すreject関数。

  • オブジェクトの状態を変化させることができる約束の解決方法は成功し、情報は、機能の後続の処理のために転送することができます
  • オブジェクトの状態を拒否することができる約束の方法に変更された故障情報は、関数で後続の処理のために転送することができます
  • 非同期操作がエラーをスローした場合、エラーを処理、キャッチメソッド指定されたコールバック関数を呼び出し、操作がエラーをスローした場合、メソッドは、コールバック関数を指定し、キャッチ撮影します

ここでの考え方は以下のとおりです。これは、非同期メソッドは同期方式のようにすることができますことができます事を返しますが、すぐに実装の最終結果を返さないが、将来の結果の代表への復帰は、プロミスオブジェクトを表示することができ次いで、に従ってプロミスオブジェクト状態異なるコールバック関数を呼び出します

ここでは、それは何のコールバックを呼び出します方法:Promise.prototype.then()ロール・インスタンスのための約束を追加することで状態を変更するコールバック関数を、この方法の最初のパラメータは、コールバック関数が解消される状態、二番目のパラメータ(オプション)は、コールバック拒否状態です。その後、次のことができますチェーンの呼び出しは、オブジェクトが約束方法であるため、自身が返されます。その後、連鎖呼び出しを使用して、呼び出しの連鎖のような非常に明確なルックスになっただけで地獄のコールバックコードは次のとおりです。

getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .then(c => getMoreData(c))
  .then(d => getMoreData(d))
  .then(e => console.log(e));

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);

しかし、ほとんどのケースでは、我々は自分自身の新しい約束を必要としませんが、約束のインスタンスオブジェクトの使用が作成されています。

次のように利点と欠点を約束:同期動作が発現することを約束オブジェクトと、プロセスは、深くネストされたコールバック関数を回避するために、非同期動作であってもよいです。欠点は次のとおりです。約束のコンストラクターが実行したときに、すぐに私たちは約束をキャンセルすることはできません、平均、executor機能を呼び出し、それは、新しい、ノーウェイト後直ちに実行されます途中でキャンセルすることはできません。あなたはコールバック関数を設定しない場合や、内部プロミスエラーが外部に反映されません。

今、私たちは約束が非同期操作を表し、要約、結果が良いか悪いか、将来の結果を保証があるだろう、状態によって区別されます。非同期オブジェクトとコールバック関数から取り外すことができる登録したコールバック関数の利点に比べthen方法非同期操作にコールバック関数を結合するためにコールバックを回避する(代わりの登録機能にコールバック関数)、地獄。この方法はプロミスオブジェクトを返すので、私たちは問題を解決するために、ネストされたコールバックのチェーンを呼び出すことにより、非常に便利な方法を持っている、と方法Promise.allがあるので、それは簡単な複数の操作を同時に実行することができます。

3.async /のawait

非同期は、非同期操作に関連付けられているES7-キーワードだけで、偉大な関連性の約束。非同期は、「非同期」速記は、非同期速記を待つ考えることができる待つです。文書の完全な名前で非同期と呼ばれasync function、平均非同期キーワードは、関数宣言の前に記述する必要があります関数は非同期で宣言します

シンタックスシュガー文は、非同期関数は、約束の関数です。非同期の役割は次のとおりです。この関数はオブジェクトが約束でなければなりません返しします

async function testAsync() {
    return "hello async";
}

const result = testAsync();
console.log(result); // Promise { 'hello async' }

非同期関数宣言は、プロミスオブジェクトを返します。関数の戻り値は、オブジェクトが、直接量約束ではない場合、非同期プロミスオブジェクトをカプセル化()Promise.resolveによってこの量を指示します。このテーマに対処するため、次に()チェーンの約束:それはオブジェクトである約束ので、当然、我々は古い方法を使用することができます。

testAsync().then(v => {
    console.log(v);    // 输出 hello async
});

対応のawaitしながら説明。オペレータを待つ、構文は次のとおりです。

[return_value] = await expression;
  • ここで式ができプロミスオブジェクトまたは任意の値を待つように
  • (あなたが約束を待っていれば値自体を返すようにしません)。
  • あなたは非同期機能/プロミスオブジェクトを待っている場合は、概念的に言えば、非同期操作の完了を待つことです。だから、それは約束の処理待ちが完了すると、現在の非同期機能の実行を中断します発現を待つコールバック関数パラメータの値として解決正常処理プロミス(成就)は、次いで、非同期funcionの実行を再開した場合。それは、すべてのプロミスオブジェクトに非同期に実行中にカプセル化されているので(そこブロックされているが、実際にコードが非同期に実行されているが、関数呼び出しの非同期は、/待つ式は、閉塞を引き起こすことはありません。また、非同期を待つ必要があります理由機能)
  • 約束は例外を(拒否)を処理する場合は、約束の異常発現がスローされます待っています。
  • オペレータは、そうでなければ、構文エラー、非同期関数非同期関数のみを使用することができる待ちます。

setTimeoutメソッドの非同期動作と今、例えば、時間のかかるシミュレーション、非同期/あなたが書くだろうか待っていないで見てみましょう

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}

takeLongTime().then(v => {
    console.log("got", v);
});

あなたは非同期を使用している場合、および/のawait、このようになります。

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
} // 这个函数本身return的就是Promise 所以加不加 async 关键字都一样

async function test() {
    const v = await takeLongTime();
    console.log(v);
}

test();

利点である場合、これら2つのコードに対処するには、2つの方法があります(つまり、プロミスオブジェクトの実際の処理である)非同期呼び出し差が偶数/のawaitいくつかのコードを記述する必要が非同期使用して、明らかにされていません、それはですか?回答:利点非同期/のawaitそのチェーンを処理します単鎖非同期/のawaitの利点を発見しませんが、あなたが約束の複数で構成される、チェーンに対処するための時間を必要とする場合、利点は、チェーンによって問題を解決するために(非常に興味深い、多層コールバックの約束を明らかにすることができますを約束そして今、非同期で/)、それを最適化し、さらに待ちます。

サービスを想定すると、いくつかのステップで完了し、各ステップは、非同期であるが、最後のステップの結果に。我々はまだ非同期操作をシミュレートするためのsetTimeoutを使用します。

/**
 * 传入参数 n,表示这个函数执行的时间(毫秒)
 * 执行的结果是 n + 200,这个值将用于下一步骤
 */
function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}

function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

function step2(n) {
    console.log(`step2 with ${n}`);
    return takeLongTime(n);
}

function step3(n) {
    console.log(`step3 with ${n}`);
    return takeLongTime(n);
}

// 现在用 Promise 方式来实现这三个步骤的处理

function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => step2(time2))
        .then(time3 => step3(time3))
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}

doIt();

// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1507.251ms

非同期/はそれを達成するために待っていた場合、それは次のようになります:

async function doIt() {
    console.time("doIt");
    const time1 = 300;
    const time2 = await step1(time1);
    const time3 = await step2(time2);
    const result = await step3(time3);
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
}

doIt();

約束して達成された結果は前と同じですが、このコードは非常にほとんど同期コードとして、明確思いません

概要:のawait式の非同期機能、役割は約束の結果が出るまで保留非同期関数は非同期関数で、戻り値を解析再開した後、出てきたようにすることです。汎用非同期/待っている同期動作プロミスを複数使用する場合に簡略化されました

最後に

基本的に、約束は、特定の関数オブジェクトが発信されている、我々は、コールバック関数(コールバック)は、それらの内部関数を渡すのではなく、「昔ながら」の着信コールバック、コールバック関数とは異なり、それを使用して接続します。その後、複数の呼び出し()は、一桁の別個のインサートで実行される多くのコールバックに追加することができます。

機能の約束 - ノーウェイト、その状況を待つことなく、非同期機能を実行するには、すぐに約束オブジェクトを返す実行されるだろうし、文の後ろにブロックされることはありません。

待つ一般的に、非同期を待っていることはすべて、補完関数を待ちます。しかし、構文によって、待ち時間は任意の式を指定できます待って、この式の結果は、プロミスオブジェクトまたは他の値です。非同期関数が約束オブジェクトを返すので、非同期機能を待つために、戻り値(約束レーン決意を)待つために使用することができます-これはまた、非同期機能を待っているの完了を待つと言うことができます。しかし、明確に、そしてそれは実際には、戻り値です。オブジェクト等待つ気づかない約束、それは任意の式の結果を待つことができ、従って、実際の関数呼び出しの背後に待つは、通常、直接または量によってアクセスすることができます。

あなたはそれが約束のオブジェクトになるまで待っていれば、あなたは忙しい待って、それはそれは約束でカプセル化されているすべての内のブロッキング、障害物が発生しない関数呼び出し.async理由を待たなければならない非同期機能で使用されている(ブロックされます非同期実行オブジェクト)コードの後ろに、プロミスは、オブジェクトを解決し、次に待つ式の計算結果として得られた値を解決待っ。

非同期は、上述した戻り値プロミスパッケージ化オブジェクトとしての機能(関数式またはラムダ)が続くことになり、プロミスを待つ完全待つ、およびそれらの決意から結果を返します。それはほとんどの同期コードとして、コードは非常に明確に見えるようになります

参照

公式文書:

ルーキーチュートリアル:

おすすめ

転載: www.cnblogs.com/ZCplayground/p/11424719.html