今回は、async/await 地獄問題への対処方法をお届けします。 async/await 地獄問題に対処する際の 注意点とは何ですか。実際のケースを見てみましょう。
はじめに
async/awaitとはasync/awaitは、coモジュールやgeneratorfunctionの糖衣構文であると言えます。より明確なセマンティクスで js 非同期コードを解決します。
co モジュールに精通している学生は、co モジュールがマスター TJ によって作成されたモジュールであり、ジェネレーター関数を使用して非同期プロセスを解決するモジュールであることを知っているはずです。ジェネレーター関数の実行者と見なすことができます。 Async/await は co モジュールへのアップグレードであり、ジェネレーター関数エグゼキューターが組み込まれており、co モジュールに依存しなくなりました。同時に、async は Promise を返します。 上記の観点から、co モジュールにしろ async/await にしろ、Promise についてよく知らない学生は、まず Promise について詳しく学ぶことができます。 async/await を書くのは素晴らしいですが、次の問題に注意する必要があります。 async/await はコールバック地獄から解放しますが、async/await 地獄の問題が生じます。async/await 地獄とは何ですか
JavaScript で非同期プログラミングを行うとき、多くの場合、ステートメントは前のステートメントに依存する必要がありません。パフォーマンスの問題を引き起こす可能性があります。
地獄の async/await の例
ピザと飲み物を買うプログラムを書いてみましょう:(async () => { const pizzaData = await getPizzaData() // async call const drinkData = await getDrinkData() // async call const chosenPizza = choosePizza() // sync call const chosenDrink = chooseDrink() // sync call await addPizzaToCart(chosenPizza) // async call await addDrinkToCart(chosenDrink) // async call orderItems() // async call })()
説明
コードを非同期 IIFE にカプセル化し、次の順序で実行しました:ピザのリストを取得するドリンクのリストを取得する
リストからピザを選択する
からドリンクを選択するリスト
選択したピザをショッピングカートに追加します
選択したドリンクをショッピングカートに追加します
ショッピングカート内の商品を注文します
質問
ここに質問があります リストからピザを選択するアクションはなぜ行われますかドリンクリストを入手するまで待つ必要がありますか?これら 2 つは無関係な操作です。関連する操作には 2 つのグループがあります: ピザ リストの取得 - 》ピザの選択 - ショッピング カートに追加するピザの選択飲み物リストの取得 - 》飲み物の選択 -> ショッピング カートに追加する飲み物の選択これら 2 つのセット操作は同時に実行する必要があります。もっと悪い例を見てみましょう
この Javascript コード スニペットは、ショッピング カート内の商品を取得し、注文リクエストを作成します。async function orderItems() { const items = await getCartItems() // async call const noOfItems = items.length for(var i = 0; i < noOfItems; i++) { await sendRequest(items[i]) // async call } }
await キーワードを忘れたらどうなるでしょうか?
非同期関数を呼び出すときに await を使用するのを忘れた場合、関数の実行を待つ必要がないことを意味します。 async 関数は、後で使用できる Promise を直接返します。(async () => { const value = doSomeAsyncTask() console.log(value) // an unresolved promise })()
exit を実行してもこの非同期タスクは完了しません。したがって、 await キーワードを使用する必要があります。
promise には興味深い属性 があり、コードの特定の行で Promise を取得し、他の場所で解決されるのを待つことができます。これが、async/await 地獄を解決する鍵となります。
(async () => { const promise = doSomeAsyncTask() const value = await promise console.log(value) // the actual value })()
应该如何避免 async/await 地狱
首先我们需要知道哪些命名是有前后依赖关系的。
然后将有依赖关系的系列操作进行分组合并成一个异步操作。
同时执行这些异步函数。
我们来重写这写例子:
async function selectPizza() { const pizzaData = await getPizzaData() // async call const chosenPizza = choosePizza() // sync call await addPizzaToCart(chosenPizza) // async call } async function selectDrink() { const drinkData = await getDrinkData() // async call const chosenDrink = chooseDrink() // sync call await addDrinkToCart(chosenDrink) // async call } (async () => { const pizzaPromise = selectPizza() const drinkPromise = selectDrink() await pizzaPromise await drinkPromise orderItems() // async call })() // Although I prefer it this way (async () => { Promise.all([selectPizza(), selectDrink()].then(orderItems) // async call })()
我们将语句分成两个函数。在函数内部,每个语句都依赖于前一个语句的执行。然后我们同时执行这两个函数 selectPizza()和selectDrink() 。
在第二个例子中我们需要处理未知数量的 Promise。处理这个问题非常简单,我们只需要创建一个数组将所有 Promise 存入其中,使用 Promise.all() 方法并行执行:
async function orderItems() { const items = await getCartItems() // async call const noOfItems = items.length const promises = [] for(var i = 0; i < noOfItems; i++) { const orderPromise = sendRequest(items[i]) // async call promises.push(orderPromise) // sync call } await Promise.all(promises) // async call }
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
vue-router3.0版本router.push无法刷新页面如何处理
以上が非同期/待機地獄の問題の処理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。