ホームページ  >  記事  >  ウェブフロントエンド  >  JS 非同期コールバック Async/Await と Promise の違い、Async/Await が Promise を置き換える 6 つの理由

JS 非同期コールバック Async/Await と Promise の違い、Async/Await が Promise を置き換える 6 つの理由

青灯夜游
青灯夜游オリジナル
2018-09-12 16:45:321545ブラウズ

この章では、JS 非同期コールバック Async/Await と Promise の違いと、Async/Await が Promise を置き換える 6 つの理由を紹介します。困っている友人は参考にしていただければ幸いです。

Async/Await とは何ですか?

async/await は、非同期コードを記述する新しい方法です。以前のメソッドはコールバック関数と Promise でした。

async/awaitはPromiseに基づいて実装されているため、通常のコールバック関数には使用できません。

async/await は、Promise と同様にノンブロッキングです。

async/await は、非同期コードを同期コードのように見せます。そこに魔法があります。

Async/Await 構文

この例では、getJSON 関数は Promise を返し、Promise が正常に解決されると JSON オブジェクトを返します。この関数を呼び出し、返された JSON オブジェクトを出力し、「done」を返すだけです。

Promise の使用は次のようになります:

const makeRequest = () =>
  getJSON()
    .then(data => {
      console.log(data)
      return "done"
    })makeRequest()

Async/Await の使用は次のようになります:

const makeRequest = async () => {
  console.log(await getJSON())
  return "done"}makeRequest()

それらにはいくつかのわずかな違いがあります:

関数の前に追加の aync キーワードがあります。 await キーワードは、aync で定義された関数内でのみ使用できます。 async 関数は暗黙的に Promise を返し、Promise の解決値は関数の戻り値になります。 (例の reosolve 値は文字列「done」です)

ポイント 1 は、async 関数内にないため、最も外側のコードで await を使用できないことを意味します。

// 不能在最外层代码中使用
awaitawait makeRequest()
// 这是会出事情的 
makeRequest().then((result) => {
  // 代码
 })

await getJSON() は、getJSON の Promise が正常に解決されるまで console.log が実行前に待機することを意味します。

なぜ Async/Await が優れているのでしょうか?

1. シンプルさ

この例からわかるように、Async/Await を使用すると、明らかに多くのコードが節約されます。 .then を書く必要はなく、Promise の解決値を処理するための匿名関数を書く必要もありません。冗長なデータ変数を定義する必要もなく、入れ子のコードも避けられます。これらの小さな利点は、次のコード例でより明らかになるように、すぐに加算されます。

2. エラー処理

Async/Await を使用すると、try/catch で同期エラーと非同期エラーの両方を処理できます。以下の Promise の例では、JSON.parse エラーが Promise 内にあるため、try/catch は JSON.parse エラーを処理できません。エラー処理コードが非常に冗長になるように、.catch を使用する必要があります。さらに、実際の製品コードはさらに複雑になります。

const makeRequest = () => {
  try {
    getJSON()
      .then(result => {
        // JSON.parse可能会出错
        const data = JSON.parse(result)
        console.log(data)
      })
      // 取消注释,处理异步代码的错误
      // .catch((err) => {
      //   console.log(err)
      // })
  } catch (err) {
    console.log(err)
  }}

aync/await が使用されている場合、catch は JSON.parse エラーを処理できます:

const makeRequest = async () => {
  try {
    // this parse may fail
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }}

3. 条件付きステートメント

次の例では、データを取得してから、直接返すか、さらに取得し続けるかを決定する必要があります。返されたデータに基づくデータ。 ·

const makeRequest = () => {
  return getJSON()
    .then(data => {
      if (data.needsAnotherRequest) {
        return makeAnotherRequest(data)
          .then(moreData => {
            console.log(moreData)
            return moreData          })
      } else {
        console.log(data)
        return data      }
    })}

これらのコードは、見ているだけで頭が痛くなります。ネスト (6 レベル)、括弧、および最終結果を最も外側の Promise に渡すだけの return ステートメントと混同されやすいです。

async/await を使用して上記のコードを記述すると、可読性が大幅に向上します:

const makeRequest = async () => {
  const data = await getJSON()
  if (data.needsAnotherRequest) {
    const moreData = await makeAnotherRequest(data);
    console.log(moreData)
    return moreData  } else {
    console.log(data)
    return data    
  }}

4. 中間値

promise1 を呼び出し、promise1 から返された結果を使用してpromise2 を呼び出し、その結果を使用するというシナリオに遭遇したことがあるでしょう。両方ともpromise3を呼び出します。コードは次のようになります:

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return promise2(value1)
        .then(value2 => {        
          return promise3(value1, value2)
        })
    })}

Promise3 が value1 を必要としない場合は、単に Promise をフラットにネストすることができます。ネストに耐えられない場合は、値 1 と 2 を Promise.all に入れて、深いネストを避けることができます:

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return Promise.all([value1, promise2(value1)])
    })
    .then(([value1, value2]) => {      
      return promise3(value1, value2)
    })}

このアプローチでは、読みやすさのためにセマンティクスが犠牲になります。ネストを避ける以外に、value1 と value2 を配列に入れる理由はありません。

async/await を使用すると、コードは非常にシンプルで直感的になります。

const makeRequest = async () => {
  const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)}

5. エラー スタック

以下の例では、Promise チェーンのどこかでエラーがスローされたと想定して、複数の Promise が呼び出されます。

const makeRequest = () => {
  return callAPromise()
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => callAPromise())
    .then(() => {
      throw new Error("oops");
    })}makeRequest()
  .catch(err => {
    console.log(err);
    // output
    // Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
  })

Promise チェーンで返されたエラー スタックは、エラーが発生した場所についての手掛かりを与えません。 。さらに悪いことに、これは誤解を招きます。エラー スタック内の唯一の関数は callAPromise と呼ばれるもので、これはエラーとは何の関係もありません。 (ファイル名と行番号は引き続き役立ちます)。

ただし、async/await のエラー スタックは、エラーが存在する関数を指します。

const makeRequest = async () => {
  await callAPromise()
  await callAPromise()
  await callAPromise()
  await callAPromise()
  await callAPromise()
  throw new Error("oops");}makeRequest()
  .catch(err => {
    console.log(err);
    // output
    // Error: oops at makeRequest (index.js:7:9)
  })

開発環境では、この利点は大きくありません。ただし、本番環境のエラーログを分析する場合には非常に役立ちます。現時点では、then チェーンでエラーが発生したことを知るよりも、makeRequest でエラーが発生したことを知る方が良いでしょう。

6. デバッグ

最後で最も重要な点は、async/await を使用するとコードのデバッグが簡単になるということです。 Promise のデバッグが面倒な 2 つの理由:

1) 式を返すアロー関数にはブレークポイントを設定できません

JS 非同期コールバック Async/Await と Promise の違い、Async/Await が Promise を置き換える 6 つの理由

2) .then コード ブロックにブレークポイントを設定する場合は、ステップ オーバー ショートカット キーを使用すると、デバッガーは非同期コードをスキップするだけなので、次の .then にはジャンプしません。

await/async を使用する場合、多くのアロー関数が必要なくなるため、同期コードをデバッグするのと同じように await ステートメントをスキップできます

JS 非同期コールバック Async/Await と Promise の違い、Async/Await が Promise を置き換える 6 つの理由

結論

Async/Await は近年 JavaScript で追加された機能です最も革新的な機能の 1 つです。これにより、Promise 構文がいかに悪いかがわかり、直感的な代替手段が提供されます。

心配

おそらく、Async/Await についていくつかの当然の疑問があるでしょう:
これにより、非同期コードがわかりにくくなります。私たちは非同期コードを識別するためにコールバック関数や .then を使用することに慣れており、新しいフラグに慣れるまでに数週間かかる場合があります。ただし、C# には長年にわたってこの機能があり、この機能に精通している友人なら、一時的に不便になってもそれだけの価値があることを知っているはずです。
Node 7 は LTS (長期サポート リリース) ではありません。ただし、Node 8 は来月リリースされる予定で、コードを新しいバージョンに移行するのは非常に簡単です。

以上がJS 非同期コールバック Async/Await と Promise の違い、Async/Await が Promise を置き換える 6 つの理由の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。