이번에는 async/await hell 문제를 처리하는 방법을 알려드리겠습니다. async/await hell 문제를 처리할 때 주의사항은 무엇인가요?
머리말
async/await
async/await은 공동 모듈과 generatorfunction에 대한 구문 설탕이라고 할 수 있습니다. 보다 명확한 의미론으로 js 비동기 코드를 해결합니다.
co 모듈에 익숙한 학생들은 co 모듈이 비동기 프로세스를 해결하기 위해 생성기 기능을 사용하는 Master TJ가 작성한 모듈이라는 것을 알아야 합니다. 생성기 기능의 실행자라고 볼 수 있습니다. Async/await는 co 모듈의 업그레이드입니다. 여기에는 생성기 함수 실행기가 내장되어 있으며 더 이상 co 모듈에 의존하지 않습니다. 동시에 async는 Promise를 반환합니다.
위의 관점에서 볼 때, co 모듈이든 async/await이든 Promise는 가장 기본적인 단위로 사용됩니다. Promise에 대해 잘 모르는 학생들은 먼저 Promise에 대해 자세히 알아볼 수 있습니다.
async/await는 작성하기에는 좋지만 이러한 문제에 주의해야 합니다.
async/await는 콜백 지옥에서 우리를 해방시켜주지만 async/await 지옥의 문제를 야기합니다.
async/await 지옥이란 무엇입니까
Javascript에서 비동기 프로그래밍을 할 때 사람들은 항상 우리의 문이 이전 문에 의존할 필요가 없는 경우가 많습니다. 성능 문제가 발생합니다.
async/await example from hell
피자와 음료수를 구매하는 프로그램을 작성해 보겠습니다.
(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로 캡슐화하고 다음 순서로 실행했습니다.
피자 목록 가져오기
음료 목록 가져오기
목록에서 피자 선택
에서 음료 선택 목록
선택한 피자를 장바구니에 추가하세요
선택한 음료를 장바구니에 추가하세요
장바구니에 있는 품목을 주문하세요
Question
여기에 질문이 있습니다. 목록에서 피자를 선택하는 동작은 왜 이루어지나요? 음료 목록을 받으려면 기다려야 하나요? 이 두 가지는 서로 관련이 없는 작업입니다. 관련 작업에는 두 그룹이 있습니다:
피자 목록 가져오기->피자 선택->장바구니에 추가할 피자 선택
음료 목록 가져오기->음료 선택->장바구니에 추가할 음료 선택
이 두 세트는 작업은 동시에 실행되어야 합니다.
더 나쁜 예를 살펴보겠습니다.
이 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 } }
이 경우 for 루프는 다음 반복을 계속하기 전에 sendRequest() 함수가 완료될 때까지 기다려야 합니다. 하지만 우리는 기다릴 필요가 없습니다. 우리는 가능한 한 빨리 모든 요청을 보내길 바랍니다. 그런 다음 모든 요청이 완료될 때까지 기다릴 수 있습니다.
이제 async/await 지옥에 대해 더 잘 이해해야 합니다. 이제 또 다른 질문을 생각해 보겠습니다.
await 키워드를 잊어버리면 어떻게 되나요?
비동기 함수를 호출할 때 Wait를 사용하는 것을 잊었다면 함수 실행을 기다릴 필요가 없다는 뜻입니다. 비동기 함수는 나중에 사용할 수 있는 약속을 직접 반환합니다.
(async () => { const value = doSomeAsyncTask() console.log(value) // an unresolved promise })()
또는 프로그램이 명확하지 않아 함수 실행이 완료될 때까지 기다리려는 경우 직접 exit을 사용하면 이 비동기 작업이 완료되지 않습니다. 따라서 wait 키워드를 사용해야 합니다.
promise에는 흥미로운 속성이 있습니다. 특정 코드 줄에서 Promise를 가져와 다른 곳에서 해결될 때까지 기다릴 수 있습니다. 이것이 async/await 지옥 문제를 해결하는 열쇠입니다.
(async () => { const promise = doSomeAsyncTask() const value = await promise console.log(value) // the actual value })()
보시다시피 doSomeAsyncTask는 Promise를 직접 반환합니다. 동시에, doSomeAsyncTask의 반환 값을 얻기 위해 비동기 함수 doSomeAsyncTask가 실행되기 시작했습니다.
应该如何避免 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!