티스토리 뷰

비동기란?

 특정 코드의 연산의 종료를 기다리지 않고 다른 코드를 먼저 실행 하는 특성이다.

만약 동기적으로 코드가 실행된다면 특정코드의 연산이 끝나고 다음 코드가 실행이 되는것이다.

비동기 처리를 통해 여러가지 작업을 동시에 할 수 있다.

 

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
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함