ホームページ > 記事 > ウェブフロントエンド > async/await の詳細
はじめに
面接中に、async/await は候補者の知識を確認する良い方法です。もちろん、この知識ポイントをどのような角度から説明するかは考えていません。インタビュアーに質問された場合は、自己実行ジェネレーターの構文糖について答えることができます。しかし、私はそれに少し気づいたでしょうか、それとも彼の認識を見たでしょうか?
babel の実装方法
注: ジェネレーターについて知らない場合は、まずジェネレーターを見て、ついでにイテレーターを見てみるのも良いでしょう。
例コード:
async function t() { const x = await getResult(); const y = await getResult2(); return x + y; }
babel 変換コード
"use strict"; function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function t() { return _t.apply(this, arguments); } function _t() { _t = _asyncToGenerator(function* () { const x = yield getResult(); const y = yield getResult2(); return x + y; }); return _t.apply(this, arguments); }
コードからわかるように、babel
は generator
を変換します。 async
の場合、_asyncToGenerator
と asyncGeneratorStep
の 2 つのステップが使用されます。
_asyncToGenerator
何をしたのか
1. _asyncToGenerator
を呼び出すと、promise
が返されましたが、これはたまたま と一致していました。 async
関数は then
機能に接続できます。
2. 成功したメソッド _next
を定義し、失敗したメソッド _throw
を定義します。 2 つの関数では、asyncGeneratorStep
が呼び出されます。 asyncGeneratorStep
を読むと、これが実際には再帰であることがわかります。
3. _next
を実行します。それが上記の自己実行ジェネレーターです。
asyncGeneratorStep
実行内容
1. Try-catch を実行して、generator
の実行中にエラーをキャプチャします。エラーが報告された場合、async
関数は直接 reject
ステータスに入ります。
2. info
の done
値が true かどうかを確認します。true の場合、イテレータが実行されたことを意味します。値を 解決できます。 ###外出。それ以外の場合は、引き続き
_next を呼び出して値を次の値に渡します。
这里我唯一没有看明白的是`_throw`,这个看代码像是执行不到的。promise.resolve状态值应该是fulfilled。看懂的 可以在评论中和我说一下,感谢。
async/await の利点
新しい構文糖衣が登場するたびに、前世代のソリューションの欠点を補わなければなりません。 例: promise の出現は、コールバック地獄 を回避するためです。これを回避する方法は、呼び出しをチェーンすることです。
async/await は何を解決しますか?
Promise コードと async/await コードの比較
Promise バージョンfunction getData() { getRes().then((res) => { console.log(res); }) }async/await バージョン
const getData = async function() { const res = await getRes(); console.log(res); }中間値
Promise を使用する場合、複数の Promise がシリアル化されると、後続の Promise が前の Promise の値を取得することが非常に困難であることがわかります。そして、async はこの問題を正確に解決します。 中間値を取得するための約束の例
const morePromise = () => { return promiseFun1().then((value1) => { return promiseFun2(value1).then((value2) => { return promiseFun3(value1, value2).then((res) => { console.log(res); }) }) }) }上記はネストされたバージョンですが、さまざまなニーズに応じてネストできない場合があります。
const morePromise = () => { return promiseFun1().then((value1) => { return promiseAll([value1, promiseFun2(value1)]) }).then(([value1, value2]) => { return promiseFun3(value1, value2).then((res) => { console.log(res); }) }) }ネストレベルは減りましたが、それでも満足のいくものではありません。 async/await 最適化の使用例
const morePromise = async function() { const value1 = await promiseFun1(); const value2 = await promiseFun2(value1); const res = await promiseFun3(value1, valuw2); return res; }シリアル非同期プロセスには中間値が含まれる必要があるため、async/await の利点は明らかです。 条件付きステートメントの状況たとえば、現在要件があるとします。データをリクエストした後、さらにデータをリクエストする必要があるかどうかを判断できます。 Promise を使用して実装した場合でも、ネストされたレベルが存在します。
const a = () => { return getResult().then((data) => { if(data.hasMore) { return getMoreRes(data).then((dataMore) => { return dataMore; }) } else { return data; } }) }ただし、async を使用してこの例を最適化すると、コードがより美しくなります。 async/await 最適化の例
const a = async() => { const data = await getResult(); if(data.hasMore) { const dataMore = await getMoreRes(data); return dataMore; } else { return data; } }async/await の欠点上で async/await の利点のいくつかについて説明しましたが、async/await は万能ではありません。 . .上記はすべてシリアル非同期シナリオに関するものです。並列非同期シナリオに移行する場合。 並列非同期シナリオ
const a = async function() { const res = await Promise.all[getRes1(), getRes2()]; return res; }
async/await エラー処理
エラー キャプチャでの async/await を実装するには、promise.all を使用する必要があります。主な側面はトライキャッチです。try-catch
const a = async () => { try{ const res = await Promise.reject(1); } catch(err) { console.log(err); } }
promise のキャッチ
これを行うためにパブリック関数を抽出できます。各 Promise の後に catch 処理が続くため、コードは非常に長くなります。const a = async function() { const res = await Promise.reject(1).catch((err) => { console.log(err); }) }
// 公共函数 function errWrap(promise) { return promise().then((data) => { return [null, data]; }).catch((err) => { return [err, null]; }) }推奨チュートリアル: 「
JS チュートリアル 」
以上がasync/await の詳細の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。