티스토리 뷰
비동기란?
특정 코드의 연산의 종료를 기다리지 않고 다른 코드를 먼저 실행 하는 특성이다.
만약 동기적으로 코드가 실행된다면 특정코드의 연산이 끝나고 다음 코드가 실행이 되는것이다.
비동기 처리를 통해 여러가지 작업을 동시에 할 수 있다.
Javascript에서의 비동기
javascript 코드는 동기적으로 실행되며, hoisting이 된 이후부터 차례대로 코드가 실행된다.
그렇다면 javascript에서는 어떻게 비동기 프로그래밍을 할 수 있을까?
일반적인 javascript로 연산하는 작업은 비동기 작업을 할 수 없다. 하지만 외부api(서버 등)에 연동할 때 비동기적인 코드를 작성할 수 있다. 외부 api가 실행되는 동안 다른 작업을 할 수 있도록 하는 것이다.
이는 javascript engine에서도 그 구조를 확인할 수 있다.
비동기 처리를 하는 이벤트를 Web api라는 공간으로 보낸다. 그 다음 Web api에서 callback queue에 보내진 후 callback queue에서 실행해야 될 이벤트가 채워진다면 event loop가 callstack과 callback queue를 바라보다 callstack이 비어있을 경우 callback queue의 내용을 callstack으로 옮겨서 이벤트가 실행되도록 한다.
https://kmj24.tistory.com/128?category=941106
Event Loop
Javascript는 run code, event collecting & processing, Queue의 하위 작업들을 담당하는 event loop에 기반한 동시성(concurrency)모델을 가지고 있다. Javascript Engine javascript 엔진은 javascript코드를..
kmj24.tistory.com
가장 쉽게 접할 수 있는 외부 api로는 setTimeout 이 있다.
setTimeout은 브라우저에서 Javascript interface를 제공하는 외부 api를 이용하며 그 동작은 javascript내부에서 행해지는 것은 아니다.
setTimeout은 두번째 인자로 넘겨준 시간(ms)이 지난 후 첫번째 인자로 넘겨준 함수가 실행 된다.
setTimeout(() => {
console.log("1초");
}, 1000);
setTimeout함수 내에 함수를 넘겨준다.
이때 넘겨주는 함수를 callback함수라고 한다.
Callback함수
callback함수는 말 그대로 나중에 실행할 함수이다.
callback함수의 활용 예시로, 비동기 처리를 하는 코드가 종료된 후 처리해야 되는 내용이 있을 수 있다.
사용자가 어떤 사이트에 로그인 하는 상황을 예로들어 보자.
1. 사용자가 email과 pw를 입력한 후 로그인 버튼을 클릭한다.
2. client는 입력된 사용자 정보를 가지고 서버에 유효한 검증인지 확인을 요청한다. 이때 요청하는 이벤트는 비동기적 으로 작동한다.
3. 이러한 요청을 보낸 후 서버의 응답을 기다린 후 그 다음 동작을 진행해야 된다.
이러한 네트워크 통신을 사용할 경우 callback함수를 사용할 수 있다.
처리되어야 하는 이벤트를 순차적으로 callback함수로 넣어주어 비동기 코드이지만 순서대로 실행될 수 있도록 한다.
setTimeout또한 같다.
setTimeout(() => {
console.log("1초");
}, 1000);
여기서 1초를 기다린 후 "1초"라는 문자열을 출력해야 할 경우 위의 코드를 쓸 수 있을 것이다.
이러한 형태를 지속적으로 사용할 경우 큰 단점이 존재한다.
function callbackRun(callback: Function, num: number){
callback();
console.log(num);
}
function callbackFu(){
callbackRun(() => {
callbackRun(() => {
callbackRun(() => {
callbackRun(() => {
callbackRun(() => {
console.log("last deps");
}, 5)
}, 4)
}, 3)
}, 2)
}, 1)
callbackRun(() => {}, 0);
console.log("first deps");
}
가독성이 매우 떨어지며 모든 callback함수내에 각각 오류처리를 해주어야 한다.(...)
이러한 callback함수의 불편함을 해소하기 위해 ES6에서 비동기 흐름을 컨트롤하기위한 Promise객체가 등장한다.
Promise
promise는 new키워드로 생성할 수 있으며 4개의 상태를 가진다.
- fulfilled : 성공
- rejected : 실패
- pending : 결과가 반한되지 않은 상태
- settled : 결과가 반환된 상태
function example(): Promise<any>{
return new Promise((resolve: any, reject: any) => {
try{
setTimeout(() => {
resolve(1);
}, 1000);
}catch(e: any){
reject(e);
}
})
}
export function promiseRun(){
example()
.then((value: any) => value + value) // promise의 실행 결과를 가져온다 => value = 1이며, 1+1 연산을 수행한다.
.then((value: any) => value + value) // 그 다음 promise가 실행되며 이전 결과값의 2에서 2+2를 수행한다.
.then((value: any) => console.log(value)) // 최종 결과는 4
.catch((error: any) => console.log(error)); //바로 위의 then에서 오류가 발생할 경우 error를 표시한다.
}
promise 객체의 실행결과를 then method내에서 받아올 수 있으며 위의 코드와 같이 연쇄적으로 실행할 수 있다. (Promise Chaning)
catch키워드를 통해 예외 처리가 가능하며 catch는 바로이전의 실행했던 결과에 대한 예외처리를 진행한다.
만약 promise chaning을 할 때, 각각의 실행 모두를 예외 처리해야 될 경우 아래와 같이 작성한다.
example()
.then((value: any) => value + value)
.catch((error: any) => console.log(error))
.then((value: any) => value + value)
.catch((error: any) => console.log(error))
.then((value: any) => console.log(value))
.catch((error: any) => console.log(error));
promise객체를 callback의 단점을 해결할 수 있다.
여기서 조금더 깔끔한 문법이 등장했는데 async await이다.
async await
async 키워드를 이용하여 함수를 만들면 그 함수는 Promise 객체를 반환한다.
그리고 await키워드를 이용하여 비동기 처리를 기다릴 수 있다.
async function request(loginData: userType){
const response = await axios.post('/login', loginData)
.then((response : AxiosResponse) => response.data)
.catch((err : AxiosError) => err);
return response;
}
서버에 로그인 요청을 보내는 간단한 함수이다.
await키워드를 작성해두면 서버에 요청을 보낸 후 서버로부터 response를 받을때 까지 기다린다.
request()함수는 Promise객체로 활용할 수 있다.
'javascript' 카테고리의 다른 글
Event - Capturing/Bubbling (0) | 2021.09.01 |
---|---|
Javascript currying (0) | 2021.06.26 |
this, arrow function (0) | 2021.06.25 |
Event Loop (0) | 2021.05.11 |
closer function (0) | 2021.04.28 |