JavaScriptのpromiseとasync awaitの違いは何ですか?


95

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

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

これは、私が基本的なpromiseを実装した方法の例/疑似コードです。

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。彼らはプログラミングスタイルに大きな価値を加えているようです。

繰り返しますが、これは私の非同期の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は、より大きな問題を解決しますか?それとも、コールバック地獄への別の解決策でしたか?

前に言ったように、私はpromiseとasyncを使用して、同じ問題を解決するのを待つことができます。非同期が解決するのを待つ特定のものはありますか?

その他の注意事項:

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


3
最初のコードブロックは、同期操作のpromiseを使用しているようです。どうしてそうするか?同期は本質的にコードを書くのが簡単なので、同期操作をpromiseにラップして強制的に非同期にする理由はほとんどありません。
jfriend00

@ jfriend00はい、そうです。コードを編集しました。ありがとう。
bozzmob 2015

2
あなたはまだ同期機能を持つ非同期ツールを使用しようとしています-今は両方のコードブロックにあります。どうして?
jfriend00

@ jfriend00わかりました。ここに私のコードgist.github.com/bozzmob/26d38b83dc37d1be37f5があります。何が悪いのか教えていただけますか?
bozzmob 2015

10
非同期と待機の目的を理解するには、たくさんの読書をする必要があるようです。ここではいくつかの記事があります:JavaScriptで非同期/待つために長い道のり簡素化非同期ES7非同期関数でコーディングし、ES7と非同期獣を飼いならします
jfriend00

回答:


74

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

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

単純なクエリやデータ操作のために、約束は簡単であることができますが、複雑なデータ操作やその他もろもろ関与があるとのシナリオに実行する場合、コードは単にあれば、何が起こっているか理解することは簡単だ見えます、それは別の言い方をする(同期だかのように、構文自体は、「偶発的な複雑さ」の形でasync/await回避できます)。

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


「偶発的な複雑さ」の意味について詳しく教えてください。また、パフォーマンスに関しては、両者に違いはありませんか?
bozzmob 2015

@ bozzmob、shaffner.us / cs / papers / tarpit.pdf <-彼はそこで「偶然の複雑さ」を説明しています。あなたのパフォーマンスの質問に関しては、私はそれを疑っています。特に、V8エンジンはそれが何であるかについてです。そこにはいくつかのパフォーマンステストがあると確信していますが、あまり心配する必要はありません。必要がない場合は、マイクロ最適化に時間を無駄にしないでください。
Josh Beam

1
どうもありがとう!これは私があなたから得たいくつかの素晴らしい情報です。そして、はい、マイクロ最適化を調べません。
bozzmob

私はこの説明役に立ったnikgrozev.com/2015/07/14/...
mwojtera

33

Async / Awaitは、より複雑なシナリオでより優れた構文を提供します。特に、ループやtry/ などのその他の特定の構成要素を処理するものcatch

例えば:

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

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


これは同じことを理解するための良い例です。それで、パフォーマンスに関しては、2つの間に違いはありませんか?そして、コードで使用する方が良いですか?Async Awaitは、少なくともあなたの例を見た後でより良いようです。
bozzmob 2015

1
@bozzmob:パフォーマンスに違いはありません。async / awaitを使い慣れている場合は、お勧めします。それは実際には公式の標準の一部ではないので、私はまだそれを使用していません。
Stephen Cleary

はい、私はそれが標準の一部ではないことに同意しますが、ReactJS(具体的にはネイティブのReact)の場合、コードの一部でそれを使用することを余儀なくされます。したがって、それらの半分は約束であり、半分は非同期待機です。それで、私はあなたにそれらの質問をしました。必要な情報をありがとう。
bozzmob

1
コードサンプルでtry / catchブロックを誰も使用しないと、多くの人が混乱したり混乱したりすると思います。
Augie Gardner、2016

そんな意味ですか?const getValue = value => value || operation1().then(operation2).then(getValue);
Sharcoux 2018

13

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

async/ await構文を理解するために最初に必要なことは、約束を強化することを意図した単なる構文上の砂糖です。実際、async関数の戻り値は約束です。async/ await構文は、非同期で同期的に書き込む可能性を与えます。次に例を示します。

約束の連鎖:

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

Async 関数:

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

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

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


7

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

プレーンJavaScript

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

非同期(ライブラリ)

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

約束

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

発電機

  • 長所
  • 非ブロッキングAPIをブロッキングAPIのように見せます
  • エラー処理を簡素化
  • ES2015仕様の一部
  • 短所
  • 補完的な制御フローライブラリが必要
  • それでも、非順次フローを実装するにはコールバックまたはプロミスが必要です
  • 非ジェネレーターベースのAPIをサンク化または約束する必要があります

非同期待機

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

これはどこからコピーされたのですか?少なくとも一部は、書籍Node.js Design Patterns(second edition)(ISBN-10:1785885588)の136〜137ページにあります
Peter Mortensen

6

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

私は最近この記事を書いて、コード例を使って、いくつかの一般的なユースケースでの約束よりも非同期/待機の利点を示しています:JavaScript非同期/待機が約束を吹き飛ばす6つの理由(チュートリアル)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.