비동기/대기 문제 처리

php中世界最好的语言
풀어 주다: 2018-05-22 11:49:45
원래의
1874명이 탐색했습니다.

이번에는 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按钮多次点击重复提交数据如何处理

vue-router3.0版本router.push无法刷新页面如何处理

위 내용은 비동기/대기 문제 처리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!