web-dev-qa-db-ja.com

JavaScriptの約束と非同期待機の違いは何ですか?

ECMAScript 6 およびECMAScript 7の機能を(バベルのおかげで)私のアプリケーション(モバイルとWebの両方)で既に使用しています。

最初のステップは、明らかにECMAScript 6レベルです。私は多くの非同期パターン、約束(本当に有望です)、ジェネレーター(なぜ*記号が付いているのかわかりません)などを学びました。これらのうち、約束は私の目的にかなり合っていました。そして、私はそれらを私のアプリケーションでかなり多く使用しています。

基本的な約束を実装した方法の例/擬似コードは次のとおりです。

var myPromise = new Promise(
    function (resolve,reject) {
      var x = MyDataStore(myObj);
      resolve(x);
    });

myPromise.then(
  function (x) {
    init(x);
});

時間が経つにつれて、ECMAScript 7の機能に出会い、そのうちの1つはASYNCAWAITのキーワード/関数です。これらを組み合わせることで、すばらしい驚きがもたらされます。約束の一部をasync & awaitに置き換え始めました。彼らはプログラミングスタイルに大きな価値を加えるようです。

繰り返しますが、ここに私の非同期、待機関数がどのように見えるかの擬似コードがあります-

async function myAsyncFunction (myObj) {
    var x = new MyDataStore(myObj);
    return await x.init();
}
var returnVal = await myAsyncFunction(obj);

構文エラー(存在する場合)は別にして、どちらもまったく同じことをしていると感じています。私はほとんどの約束をasync、awaitsに置き換えることができました。

Promiseが同様の仕事をするときにasync、awaitが必要なのはなぜですか?

Async、awaitはより大きな問題を解決しますか?それとも、それは地獄をコールバックするための単なる別の解決策でしたか?

先ほど言ったように、promisesとasync、awaitを使用して同じ問題を解決することができます。非同期が解決するのを待つ特定の何かがありますか?

その他の注意事項:

私はReactプロジェクトとNode.jsモジュールでasync、awaits、promiseを広範囲に使用しています。 Reactは特に初期段階であり、多くのECMAScript 6およびECMAScript 7機能を採用しています。

73
bozzmob

Promisesが同様の仕事をするときにasync、awaitが必要なのはなぜですか? async、awaitはより大きな問題を解決しますか?

async/awaitは、単に非同期コードに同期感を与えます。これは、非常にエレガントな形式の構文糖です。

単純なクエリとデータ操作の場合、Promisesは単純になりますが、複雑なデータ操作と関係のないシナリオが発生した場合、コードが単純に見た場合に何が起こっているかを理解しやすくなります同期的であるかのように(別の言い方をすれば、構文自体はasync/awaitが回避できる「偶発的な複雑さ」の形式です)。

知りたい場合は、 co (ジェネレーターと一緒に)のようなライブラリを使用して、同じような感覚を与えることができます。このようなものは、async/awaitが最終的に(ネイティブに)解決する問題を解決するために開発されました。

61
Josh Beam

Async/Awaitは、より複雑なシナリオではるかに優れた構文を提供します。特に、ループまたはtry/catchのような特定の他の構造を扱うもの。

例えば:

while (!value) {
  const intermediate = await operation1();
  value = await operation2(intermediate);
}

この例は、Promiseを使用するだけでかなり複雑になります。

29
Stephen Cleary

ここでの私の質問は、Promisesが同様の仕事をするとき、なぜasync、awaitが必要なのですか? async、awaitはより大きな問題を解決しますか?それとも、それは地獄のコールバックの単なる別の解決策でしたか?前に言ったように、PromisesとAsync、Awaitを使用して同じ問題を解決できます。 Async Awaitが解決した具体的なことはありますか?

async/await構文は、約束を補強するための単なる構文上のシュガーであるということを最初に理解する必要があります。実際、async関数の戻り値は約束です。 async/await構文を使用すると、非同期で同期的に書き込むことができます。以下に例を示します。

Promise chaining:

function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}

Async function:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}

上記の例では、awaitはプロミス(fetch(url))が解決または拒否されるのを待ちます。 promiseが解決された場合、値はresponse変数に格納され、promiseが拒否されるとエラーがスローされ、catchブロックに入ります。

async/awaitを使用すると、Promiseチェーンよりも読みやすくなることがすでにわかりました。これは、使用しているプロミスの量が増えた場合に特に当てはまります。 Promiseチェーンとasync/awaitの両方が、コールバック地獄の問題を解決し、どの方法を選択するかは個人の好みの問題です。

9

長所と短所との完全な比較。

プレーンJavaScript

  • 長所
  • 追加のライブラリやテクノロジーを必要としません
  • 最高のパフォーマンスを実現
  • サードパーティのライブラリとの最高レベルの互換性を提供します
  • アドホックでより高度なアルゴリズムの作成が可能
  • 短所
  • 追加のコードと比較的複雑なアルゴリズムが必要になる場合があります

非同期(ライブラリ)

  • 長所
  • 最も一般的な制御フローパターンを簡素化
  • まだコールバックベースのソリューションです
  • 良好なパフォーマンス
  • 短所
  • 外部依存関係を導入します
  • 高度なフローにはまだ十分でない可能性があります

約束

  • 長所
  • 最も一般的な制御フローパターンを大幅に簡素化
  • 堅牢なエラー処理
  • ES2015仕様の一部
  • OnFulfilledおよびonRejectedの遅延呼び出しを保証します
  • 短所
  • PromisifyコールバックベースのAPIが必要です
  • 小さなパフォーマンスヒットを導入

ジェネレーター

  • 長所
  • 非ブロッキングAPIをブロッキングAPIのように見せます
  • エラー処理を簡素化
  • ES2015仕様の一部
  • 短所
  • 補完的な制御フローライブラリが必要
  • コールバックまたは非シーケンシャルフローを実装する約束が依然として必要
  • Thunkifyまたはpromisifyの非ジェネレータベースのAPIが必要です

非同期待機

  • 長所
  • ノンブロッキングAPIをブロッキングのように見せます
  • わかりやすく直感的な構文
  • 短所
  • バベルまたは他のトランスパイラーといくつかの構成を今日使用する必要があります
7
Bozhinovski

Async/awaitは、複雑な制御フローが必要な場合に、コードをよりクリーンで読みやすくするのに役立ちます。また、よりデバッグしやすいコードを生成します。また、try/catchだけで同期エラーと非同期エラーの両方を処理できます。

私は最近、コード例を使用して、いくつかの一般的なユースケースでの約束に対するasync/awaitの利点を示すこの投稿を書きました https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises- away-tutorial-c7ec10518dd9

6
Gaafar

両方とも非同期コードを処理する方法です。ただし、それぞれの実行には違いがあります。実行中の実行は次のとおりです-

約束

Promiseオブジェクトは、非同期操作の可能な完了(または失敗)とその結果の値を表します。これは、作成時に必ずしも既知ではない値のプロキシであり、非同期操作の将来の結果を表します。

呼び出し元のコードは、次のステップを実行する前にその約束が満たされるまで待つことができます。そのため、Promiseにはthenという名前のメソッドがあり、Promiseが満たされたときに呼び出される関数を受け入れます。

非同期/待機

async関数が呼び出されると、Promiseを返します。 async関数が値を返すと、Promiseは返された値で解決されます。 async関数が例外または何らかの値をスローすると、Promiseはスローされた値で拒否されます。

非同期関数にはawait式を含めることができます。これは、非同期関数の実行を一時停止し、渡されたPromiseの解決を待機してから、非同期関数の実行を再開し、解決された値を返します。

async/await over promiseの長所

  • Async/awaitは、非同期操作の継続セマンティクスにクリーンな構文を提供するために構築されます。
  • コールバック/約束の地獄を回避します。
4
Samiksha Jagtap