이 장에서는 js 비동기 콜백 Async/Await와 Promise의 차이점과 Async/Await가 Promise를 대체하는 6가지 이유를 소개합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
Async/Await란 무엇인가요?
async/await는 비동기 코드를 작성하는 새로운 방법입니다. 이전 메서드는 콜백 함수와 Promise였습니다.
async/await는 Promise를 기반으로 구현되어 일반 콜백 함수에는 사용할 수 없습니다.
async/await는 Promise와 마찬가지로 비차단입니다.
async/await는 비동기 코드를 동기 코드처럼 보이게 하는데, 바로 여기에 마법이 있습니다.
Async/Await 구문
예제에서 getJSON 함수는 약속이 성공적으로 해결되면 JSON 개체를 반환하는 약속을 반환합니다. 우리는 이 함수를 호출하고, 반환된 JSON 객체를 인쇄하고 "완료"를 반환합니다.
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로 정의된 함수 내에서만 사용할 수 있습니다. 비동기 함수는 암시적으로 약속을 반환하며 약속의 확인 값은 함수 반환 값입니다. (예제에서 reosolve 값은 "done" 문자열입니다.)
포인트 1은 비동기 함수 내에 있지 않기 때문에 가장 바깥쪽 코드에서 Wait를 사용할 수 없음을 의미합니다.
// 不能在最外层代码中使用 awaitawait makeRequest() // 这是会出事情的 makeRequest().then((result) => { // 代码 })
await getJSON()은 getJSON 약속이 실행되기 전에 성공적으로 해결될 때까지 console.log가 대기한다는 의미입니다.
왜 Async/Await가 더 나은가요?
1. 단순성
예에서 볼 수 있듯이 Async/Await를 사용하면 많은 코드가 절약됩니다. 그러면 Promise의 확인 값을 처리하기 위해 익명 함수를 작성할 필요가 없고 중복된 데이터 변수를 정의할 필요가 없으며 중첩된 코드를 피할 수 있습니다. 이러한 작은 이점은 빠르게 추가되며, 다음 코드 예제에서 더욱 분명해집니다.
2. 오류 처리
Async/Await를 사용하면 try/catch를 통해 동기 및 비동기 오류를 모두 처리할 수 있습니다. 아래 Promise 예제에서 try/catch는 Promise 내부에 있기 때문에 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 } })}
보기만 해도 머리가 아픈 코드들입니다. 최종 결과를 가장 바깥쪽 Promise에 전달하기만 하면 되는 중첩(6개 수준), 괄호 및 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를 중첩할 수 있습니다. 중첩을 참을 수 없다면 Promise.all에 값 1과 2를 넣어 깊은 중첩을 피할 수 있습니다.
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) 표현식을 반환하는 화살표 함수에는 중단점을 설정할 수 없습니다.
2) .then 코드 블록에 중단점을 설정하는 경우 Step Over 단축키를 사용하면 디버거가 비동기 코드를 건너뛰기 때문에 다음 .then으로 점프하지 마세요.
await/async를 사용하면 더 이상 많은 화살표 함수가 필요하지 않으므로 동기 코드를 디버깅하는 것처럼 wait 문을 건너뛸 수 있습니다.
Conclusion
Async/Await는 최근 몇 년간 JavaScript에 추가된 기능입니다. 가장 혁신적인 기능 중 하나입니다. Promise 구문이 얼마나 나쁜지 깨닫게 하고 직관적인 대안을 제공합니다.
걱정
Async/Await에 대해 합리적인 의심이 있을 수도 있습니다.
이는 비동기 코드를 덜 명확하게 만듭니다. 우리는 비동기 코드를 식별하기 위해 콜백 함수나 .then을 사용하는 데 익숙하며 새 플래그에 익숙해지는 데 몇 주가 걸릴 수 있습니다. 그러나 C#에는 수년 동안 이 기능이 있었으며 이 기능에 익숙한 친구들은 일시적인 불편함이 그만한 가치가 있다는 것을 알아야 합니다.
Node 7은 LTS(장기 지원 릴리스)가 아닙니다. 그러나 Node 8은 다음 달에 릴리스될 예정이므로 코드를 새 버전으로 마이그레이션하는 것은 매우 간단합니다.
위 내용은 js 비동기 콜백 Async/Await와 Promise의 차이점, Async/Await가 Promise를 대체하는 6가지 이유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!