-
<Java Script > 비동기 통신JavaScript 2023. 10. 11. 11:43
오늘은 자바스크립트이 비동기 작업에 대해서 알아보겠습니다.
비동기 통신이란?
대부분의 SPA 프로그램에서 서비스를 구현 할 때
(Single Page Application) -> 웹 클라이언트가 페이지에 컨텐츠를 구성할 때서버에 다중의 페이지 요청을 해서 페이지 단위로 Response 를 받는게 아닌,
데이터만 요청해서 받은 후 하나의 페이지에서 ReRendering 하는 형태의 서비스이다,
비동기 통신이 필요한 경우
외부 API 가 Get 할 때 (외부 서버에 RESTFUL 서비스 호출 시)
파일에 접근 할 때
데이터가 큰 이미지나 컨텐츠 등을 접근해서 뿌려줄 때
비동기 통신에 필요한 객체 두가지
ES6 문법에서 제안된 비동기 통신의 수행하는 대표적인 API Promise 객체가 있고
여기서 더 진화된 Asynch & Await API 가 있다.
Promise 객체
클라이언트는 요청을 보내고 응답을 받는다.
그 응답을 분석하고 성공하면 success 실패하면 reject 를 보낸다.
그 과정에서 요청과 응답 사이에는 딜레이가 생성된다.
그 후 비동기 요청이 되어지고 xhr.onload(JsonObj) => (callback->cakkback => call) callback 지옥이 시작된다.
이걸 개선하기 위해 promise 객체가 생성되었고 특정 톨백을 수행하도록 정의한다.
실패 시에도 예외를 처리하도록 정의해야하고 methodChain 을 도입해서 다중 콜백을 처리할 수 있도록 제안된다.
Promise 객체 생성 법
const devide = (num1, num2) => { return new Promise((resolve, reject) => { }) }
promise 사용 안 한 예
function increaseAndPrint(n, callback) { // 숫자 n을 파람으로 받아서 다섯번에 겹쳐 1초 후에 1씩 더해서 출력하는 로직 작성 // 1초 마다 주기적으로 수행 되어야 하기 때문에 스크립트에서 쓰레드 역할을 하는 setTimeOut 메서드 이용 setTimeout(()=>{ const incresed = n + 1; console.log(incresed); if(callback){ callback(incresed); } },1000); }
Promise는 대표적으로 다음과 같은 3가지 상태를 가진다.
- Pending(대기): 비동기 처리 로직이 아직 미완료인 상태
- Fulfilled(이행): 비동기 처리가 완료되어 promise가 결과 값을 반환해준 상태
- Rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태
메서드
- then() : promise 에서 resolve 가 리턴되어 콜백 처리를 한 후 다음 콜백을 처리할 경우에 then(calback) 을 연속으로 호출해서 처리하도록 제안한다.
- catch(): 요청이 reject 되었을 때, 처리할 예외 핸들링 메서드.
promist 사용
요청에대한 성공 실패를 리턴하는 객체 성공 시엔 resolve 를 아닌경우 reject 호출
아래 예시에서는 resolve를 사용해보겠습니다.
const myPromise =new Promise((resolve,reject)=>{ setTimout(()=>{ resolve(1); },1000); });
Promise 객체 메서드인 then 을 이용해보자.
myPromise.then(n=>{ console.log(n); });
실행결과
이번엔 reject를 사용해보겠습니다.
const myPromise =new Promise((resolve,reject)=>{ setTimout(()=>{ reject(new Error()); // 작업 실패 },1000); });
myPromise.then(n=>{ console.log(n); }).catch(error=> { console.log(error); });
이번에는 직접 promise 생성자를 리턴하는 로직을 짜보겠습니다.
function increaseAndPrint(n) { //Promise 를 정의해서 성공/실패를 주도록 리턴시키고, 호출하는 로직은 then(), catch() 로 콜백 정의하도록 한다. return new Promise((resolve, reject)=>{ setTimeout(()=>{ const value = n + 1; if(value ==5){ const error = new Error(); error.name = ' 5번 이상 호출'; reject(error); return; } console.log(value); resolve(value); },1000); }); }
실행결과 pending 이 뜬 걸 확인 하면 성공적이라는 것을 볼 수 있다 .
이제 catch 를 이용해 에러까지 던지는 코드를 보여드리겠습니다.
increaseAndPrint(0).then(n=>{ return increaseAndPrint(n) }).then(n=>{ return increaseAndPrint(n) }).then(n=>{ return increaseAndPrint(n) }).then(n=>{ return increaseAndPrint(n) }).then(n=>{ return increaseAndPrint(n) }).catch(e => { console.log(e); });
이렇게 작성 후 실행 하면,,
실행결과 이렇게 정상적으로 실행되는 것을 볼 수 있다!
increaseAndPrint(0) .then(increaseAndPrint) .then(increaseAndPrint) .then(increaseAndPrint) .then(increaseAndPrint) .catch(e=>console.log(e));
이렇게 사용해도 똑같은 결과를 보여준다.
ES8 에서 제공하는 비동기통신
asych, await
기존 Promise 도 어렵고 then 의 중복 사용으로 콜백이 증가하는 걸 좀 더 쉽게 하기 위한 문법이다.
반드시 기억할 건 await 는 asynch 함수 내부에서만 호출 가능하다는 것이다.
asych , await 코드 예제
function sleep(ms) { return new Promise(resolve => setTimeout(resolve,ms)); }
async function proccess() { console.log('hi'); await sleep(5000); console.log('hello'); }
proccess() 를 호출 하면..
실행결과 이렇게 실행된다.
await 는 async 에 실행이 끝날 때 까지 지정된 시간을 기다린 후 하위 로직이 돌아가게 한다
자바의 synchronized와 같은 개념인 거 같다.
이번에는 then 을 사용해보자
process() .then(() =>{ console.log('Promise 에서 success 가 리턴되어 이 콜백을 수행'); });
실행결과 then 이 실행되는 순서는 await 후 다음 수행문을 실행하고 나서 라는 것을 확인 할 수 있다.
위에서 정의한 sleep 함수를 재정의 해서 다른 예제 코드를 보여드리겠습니다.
function sleep(ms) { return new Promise(resolve => setTimeout(resolve,ms)); };
이렇게 수정 후 아래에는 asynch 함수 객체 몇 개를 정의해서 각각 수행하도록 정의합니다.
비동기 통신을 각각 정의 해보자,
const getDog2 = async() => { await sleep(3000); return '왈왈'; }; const getCat = async() => { await sleep(1000); return '냥냥'; }; const getDuck = async() => { await sleep(2000); return '꽥꽥'; };
정의 후 proccess 라는 함수에 하나로 합쳐 수행해보겠습니다.
async function proccess(){ const dog =await getDog2(); console.log(dog); const cat =await getCat(); console.log(cat); const duck =await getDuck(); console.log(duck); };
지정한 await 단위로 출력 되는 걸 확인 할 수 있다.
실행결과 promise 의 메서드 중에 all([await 함수, 함수...]) 를 실행하면 각각 독립적으로 수행한다.
all 메서드를 이용해 위 proccess 메서드를 재정의 하겠습니다.
async function proccess(){ const result = await Promise.all([getDog2(), getCat(), getDuck()]); console.log(result); };
이렇게 하면 모든 쓰래드가 동시에 실행하고 (상위 쓰래드가 끝날 때 까지 대기 안 함)
모든 쓰래드가 끝나고 나서 모든 함수의 await 하위 수행문을 동시에 출력한다.
실행결과 all 메서드이 단점
메서드 사용 시 비동기 결과가 하나라도 reject 이면 모두 reject 로 간주한다.
( 모든 쓰래드를 비동기적으로 한번에 수행하기 때문인 거 같다.)
다음 포스팅에서는 이것을 이용한 실습 예제를 보여드리겠습니다.
'JavaScript' 카테고리의 다른 글
< Java Script > 비동기 통신 이용한 실습 (1) 2023.10.11