-
JS (ES6 & above) - async / await자바스크립트 Study/자바스크립트 2021. 5. 12. 01:27
■ Promise chaining
> 효율적이기는 하나, 좀 난잡해질 수 있음
Promise 생성이후 return 하는 등의 일련의 과정이 typing이 많다
계속 중첩하면 사실상 callback hell이랑 생긴게 다른게 없어질 정도!
> 간편한 api async / await을 통해 동기 형식으로 Promise 비동기를 쉽게 구현할 수 있게 함
( synthatic sugar - like class in JS )
내글 참조 :
korshika.tistory.com/99?category=955367
■ 비동기란?
내글 참조 :
> 즉 async / await은 비동기가 아닌 로직을 비동기 처리를 하여
User experience를 저해하지 않으면서 UI를 block하지 않고, loading / Event 등 을 block하지 않게 하는 것
> Promise 생성자를 사용
■ Async
1) 일반적 new Promise syntax
function fetchUser() { // do network request in 10 seconds... // async 처리 없을 시, 여기서 hold되어 user exprience 좋지 않음 // resolve / reject 결과를 resolve / reject 콜백으로 넘겨주지 않으면 // 계속 pending 상태가 되므로 유의 return new Promise((resolve, reject) => { resolve( 'ellie' ); }); } const user = fetchUser(); console.log(user); >>> Promise { 'ellie' } user.then(name => console.log(name)); >>> ellie
2) async syntax
> Promise를 생성하여 return 해줌
async function async_fetchUser() { // do network request in 10 seconds... // new promise syntax를 async가 대신 수행 return 'ellie'; } const user_2 = async_fetchUser(); console.log(user_2); user_2.then(name => console.log(name)); >>> Promise { 'ellie' } ellie
■ Await
1) 정의 :
> new Promise ( OR async ) syntax 로 작성된 함수의 결과를 받을 때까지 비동기적으로 기다림
기다리지 않으면 결과를 받기 전에 상위 context의 로직이 동기적으로 수행되어버림, 값을 못기다리고 출력
> async + await syntax를 사용
> Promise / async syntax는 반드시 resolve/reject OR return 값이 있어야 함
2) 예시 :
// 2. await function delay(ms, request_name) { return new Promise((resolve, reject)=>{ console.log(`request of ${request_name} is pending now!`); setTimeout(()=>{ console.log(`${request_name} finished..!`); resolve(ms); },ms); // setTimeout이미 비동기 함수 }); } async function getApple(){ await delay(3000, 'getApple'); return 'Apple!'; } async function getApple_nonasync(){ delay(3000, 'getApple_nonasync'); return 'Apple_noasync!'; } async function getBanana(){ await delay(2000, 'getBanana'); return 'Banana!'; } const apple = getApple(); const apple_noasync = getApple_nonasync(); const banana = getBanana(); apple.then(console.log); apple_noasync.then(console.log); banana.then(console.log); >>> request of getApple is pending now! request of getApple_nonasync is pending now! request of getBanana is pending now! // 주의! -> 이부분 바로 출력, await으로 기다리지 않았기때문 // 마지막에 pending된거 따로 값이 나오는 것을 확인할 수 있음 // ( getApple_nonasync finished..! ) Apple_noasync! getBanana finished..! Banana! getApple finished..! Apple! getApple_nonasync finished..!
3) 비동기 처리
(a) 나쁜 예제
- 콜백 지옥과 유사하게 chaning을 많이 해버려서 가독성이 낮음
function pick_fruit_badExample(){ return getApple() .then((apple)=> { return getBanana((banana)=>{ return `${apple} + ${banana}`; }); }); } pick_fruit_badExample().then(console.log); >>> request of getApple is pending now! getApple finished..! request of getBanana is pending now! getBanana finished..! Banana!
(b) 좋은 예제
async function pick_fruit_goodExample(){ const apple = await getApple(); // 여기서 기다림 const banana = await getBanana(); return `${apple} + ${banana}`; } pick_fruit_goodExample().then(console.log); >>> request of getApple is pending now! getApple finished..! request of getBanana is pending now! getBanana finished..! Apple! + Banana!
■ async / await 에러 handling
> 다음과 같은 에러 상황 가정
async function getApple(){ await delay(1000, 'getApple'); throw 'Error'; // 에러를 발생시킨 경우 return 'Apple!'; } async function getBanana(){ await delay(2000, 'getBanana'); return 'Banana!'; } // ... 중략 ...
> 비동시 await을 미리 선언하여 내부코드 병렬적으로 수행하고
결과를 기다리도록 await 사용
> 에러 발생시 try .. catch .. finally synctax로 잡음
> 함수 상위 scope에서 .then( .. ) .catch( ... ) 형식도 가능!
mdn 글 참조 : ko.javascript.info/async-awaitasync function pick_fruit_goodExample(){ try{ const apple_promise = getApple(); // 여기서 내부 코드 바로 수행 const banana_promise = getBanana(); let apple = await apple_promise(); // 여기서 기다림 let banana = await banana_promise(); return `${apple} + ${banana}`; } catch(e) { console.log(`error : ${e}`); let apple = 'fallback_apple!'; let banana = "fallback_banana!"; return `${apple} + ${banana}`; } finally { } }
※ MDN 글
await가 던진 에러는 throw가 던진 에러를 잡을 때처럼 try..catch를 사용해 잡을 수 있습니다.
async function f() { try { let response = await fetch('http://유효하지-않은-주소'); } catch(err) { alert(err); // TypeError: failed to fetch } } f();
try..catch가 없으면 아래 예시의 async 함수 f()를 호출해 만든 프라미스가 거부 상태가 됩니다. f()에 .catch를 추가하면 거부된 프라미스를 처리할 수 있습니다.
async function f() { let response = await fetch('http://유효하지-않은-url'); } // f()는 거부 상태의 프라미스가 됩니다. f().catch(alert); // TypeError: failed to fetch // (*)
■ Useful Promise APIs
1) Promise.all( ... )
> promise의 all로 promise 배열을 전달하여, 병렬적으로 기다리면서 return을 모아서 return
> 배열을 .join을 통해 string 값을 묶어주는 api도 추가로 사용
function pickAllFruits(){ return Promise.all([getApple(), getBanana()]) .then(fruits_arr => fruits_arr.join('+')); } pickAllFruits().then(console.log); >>> request of getApple is pending now! request of getBanana is pending now! getApple finished..! getBanana finished..! Apple!+Banana!
2) Promise.race( ... )
> 배열에 가장 먼저 전달되는 값을 받고 나머지는 기다리지 않음
function pickOnlyOne(){ return Promise.race([getApple(), getBanana()]); } pickOnlyOne().then(race=>console.log('single output : ', race)); >>> request of getBanana is pending now! getApple finished..! single output : Apple! // 가장 먼저 도달한 값만 받아옴! getBanana finished..!
참조 :
www.youtube.com/watch?v=aoQSOZfz3vQ&list=PLv2d7VI9OotTVOL4QmPfvJWPJvkmv6h-2&index=13&t=44s
반응형'자바스크립트 Study > 자바스크립트' 카테고리의 다른 글
JS (ES6 & above) - Promise (0) 2021.05.06 JS (ES6 & above) - 비동기란? (0) 2021.05.03 JS (ES6 & above) - JSON (0) 2021.04.27 JS (ES6 & above) - Useful Array API(methods) (0) 2021.04.26 JS (ES6 & above) - Objects (0) 2021.04.17