-
Promise & async / await⏰ 오늘의 공부/기타 2020. 1. 27. 01:32
node.js 와 react 를 다루면서 비동기 처리를 제대로 하지 못해 드럽게 코드를 짜고 있는 나를 보면서 꼭 정리를 하겠다 생각했었는데
마침 설연휴를 맞아 제대로 공부하면서 자바스크립트 비동기 처리 !!!! 마스터 하고자 한다.
Promise ?
자바스크립트 비동기 처리에 사용되는 객체
그렇다면 비동기 처리란 ?
‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성’
→ 자칫하다가 Callback hell 에 빠질 수 있다.. like 마치 내 예전 코드들처럼 ㅎ
promise 의 3가지 상태
- pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
- fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
- rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태
pending - new Promise() 메소드 호출하면 pending 상태가 된다.
new Promise(function (resolve, reject) { // ... });
Fulfilled - 콜백 함수의 인자 resolve 를 아래와 같이 실행하면 Fulfilled 가 된다.
new Promise(function (resolve, reject) { resolve(); });
function getData() { return new Promise(function (resolve, reject) { var data = 100; resolve(data); }); } // resolve()의 결과 값 data를 resolvedData로 받음 getData().then(function (resolvedData) { console.log(resolvedData); // 100 });
이행 상태에서 then()을 활용하여 처리 결과 값 받는다.
Rejected - reject 인자로 reject() 메소드를 실행하면 rejected 상태
new Promise(function (resolve, reject) { reject(); });
function getData() { return new Promise(function (resolve, reject) { reject(new Error("Request is failed")); }); } // reject()의 결과 값 Error를 err에 받음 getData().then().catch(function (err) { console.log(err); // Error: Request is failed });
실패 상태가 되면 실패 처리의 결과 값을 catch()로 받을 수 있다.
여러 개의 프로미스 연결하기
function getData() { return new Promise({ // ... }); } // then() 으로 여러 개의 프로미스를 연결한 형식 getData() .then(function (data) { // ... }) .then(function () { // ... }) .then(function () { // ... });
Promise에서 에러 처리하기 - catch()
// catch()로 오류를 감지하는 코드 function getData() { return new Promise(function (resolve, reject) { resolve('hi'); }); } getData().then(function (result) { console.log(result); // hi throw new Error("Error in then()"); }).catch(function (err) { console.log('then error : ', err); // then error : Error: Error in then() });
async / await
- async와 await는 자바스크립트의 비동기 처리 패턴 중 가장 최근에 나온 문법
- 기존의 비동기 처리 방식인 콜백 함수와 프로미스의 단점을 보완하고 개발자가 읽기 좋은 코드를 작성할 수 있게 도와준다.
기본 문법
async function 함수명() { await 비동기_처리_메소드_명(); }
- 먼저 함수의 앞에 async 라는 예약어를 붙인다.
- 그러고 나서 함수의 내부 로직 중 HTTP 통신을 하는 비동기 처리 코드 앞에 await를 붙인다.
- (주의해야 할 점 : 비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await가 의도한 대로 동작한다 ! )
실용 예제
async / await 문법이 가장 빛을 발하는 순간 : 여러개의 비동기 처리 다룰 때
await 사용하기 위해서는 먼저 Promise 함수 정의하여야 한다 !
function fetchUser() { var url = 'https://jsonplaceholder.typicode.com/users/1' return fetch(url).then(function(response) { return response.json(); }); } function fetchTodo() { var url = 'https://jsonplaceholder.typicode.com/todos/1'; return fetch(url).then(function(response) { return response.json(); }); } async function logTodoTitle() { var user = await fetchUser(); if (user.id === 1) { var todo = await fetchTodo(); console.log(todo.title); // delectus aut autem } }
- fetchUser()를 이용하여 사용자 정보 호출
- 받아온 사용자 아이디가 1이면 할 일 정보 호출
- 받아온 할 일 정보의 제목을 콘솔에 출력
await 문법은 Async 함수 안에서만 사용이 가능하고, async 내에서라고 해도 함수 안에 선언된 경우 사용이 불가하다.
→ 아래와 같이 fn 이라는 함수 안에서 await 문법은 문법적 오류가 발생
async function asyncMain () { let fn = ()=> { let data = await asyncFunction1('hello'); return data; }; let result = fn(); console.log(result); } asyncMain();
에러 처리 - try catch 활용
async function logTodoTitle() { try { var user = await fetchUser(); if (user.id === 1) { var todo = await fetchTodo(); console.log(todo.title); // delectus aut autem } } catch (error) { console.log(error); } }
catch 를 통해 발생한 네트워크 오류 뿐 아니라 간단한 타입 오류까지 잡아낼 수 있다.
발견한 error 는 error 객체에 담기기 때문에 유형에 맞게 에러 처리 가능하다.
이걸 바탕으로 코드 리팩토링을 진행했다...속이 다 시원하다. 후
참고 : https://joshua1988.github.io/web-development/javascript/promise-for-beginners/