본문 바로가기
정리/Javascript

[Javascript]비동기 처리(callback, promise, async/await)

by 꾸준한 개발 2022. 4. 4.
반응형

Javascript는 단일 스레드(single thred)이기 때문에 한번에 여러 번 일을 못하고 동기적으로 문제를 해결해 나갑니다. 하지만 api나 시간이 걸리는 작업을 할 때는 단일 스레드에서는 동기적으로 문제를 해결하다 보면 프로젝트 실행 시 딜레이가 생깁니다. 이를 해결하기 위해 비동기가 나왔습니다. Javascript에서는 3가지 방법을 사용해서 비동기 처리를 하고 있습니다.

 

1. Callback

2. Promise

3. async/await

 

비동기 처리란?
자바스크립트에서 비동기 처리는 특정 코드가 끝날때 까지 코드의 실행을 멈추지 않고 다음 코드들을 먼저 실행하는 것입니다.

 

콜백 함수(Callback)


콜백 함수란 다른 함수에 매개변수로 넘겨주는 것을 말하는데요. 

즉 말 그대로 나중에 호출하는 함수입니다. 

 

아래 예시를 보겠습니다.

function findName(name) {
    console.log('what is your name?'); //--- (1)
    console.log('...finding');  //--- (2)
    setTimeout(() => {
        console.log('your name is ' + name); //--- (3)
    }, 3000);
	console.log('right?'); //--- (4)
}

findName('홍길동');

순서
// 'what is your name?' --- (1)
// '...finding' --- (2)
// 'right?' --- (4)
//
// 3초 후
// 'your name is 홍길동' --- (3)

위에 예시를 순서를 보면 findName함수 안에 setTimeout 인 비동기 함수가 있습니다. 비동기 함수는 받기전에 바로 처리 가능한 1, 2, 4 코드들을 처리하고 3초후에 3번을 처리했습니다. 비동기함수는 후순위로 밀려나기 때문에 저희가 기대하는 결괏값을 얻지 못했습니다.

 

그래서 callback함수 사용해서 비동기 처리를 해줘서 동기적으로 코드가 작성하는 것처럼 보여줄 수 있습니다.

 

function findName (name) {
	if (!name) return console.log("Sorry, I don't know you");
	console.log('your name is ' + name); //--- (3)
	console.log('right?');  //--- (4)
}

function delay(id, cb) {
    console.log('what is your name?'); //--- (1)
    console.log('...finding'); //--- (2)
    setTimeout(() => {
        const data = { 1: '홍길동', 2: '스펀지밥' };
        cb(data[id]);
    }, 3000);
}

delay(1, findName);

// 'what is your name?' --- (1)
// '...finding' --- (2)
// 3초 후
// 'your name is 홍길동' --- (3)
// 'right?' --- (4)

 

위에 간단하게 data id를 받고 id에 맞는 이름을 찾아주는 함수를 만들어 보았습니다. 콜백 함수를 사용해서 내가 원하는 결과를 얻게 할 수 있습니다.

 

Promise


Promise가 나오게 된 이유는 callback함수를 사용해서 비동기 처리를 해주게 되면 콜백 지옥이 나와 코드가 이해하기 힘들고 지저분해질 수 있습니다. 또한 error를 잡아 내는 것 또한 확인하기 힘들었습니다. 하지만 promise로 성공과 실패를 확인할 수 있고 오류 또한 catch메서드로 잡아 낼 수 있게 되었습니다.

const findName = (id) => new Promise((resolve, reject) => {
	console.log('what is your name?'); //--- (1)
   	console.log('...finding'); //--- (2)
	setTimeout(() => {
        const data = { 1: '홍길동', 2: '스펀지밥' };
        if (typeof id !== 'number') return reject(new Error("Id type is number!")); --(ㄱ)
		if (!data[id]) return reject("Sorry, I don't know you");
        resolve('your name is ' + data[id]);
    }, 3000);
})
 .then(data => {
     console.log(data);
     console.log('right?');
 }, console.log)
 .catch(console.log);

// 'what is your name?' --- (1)
// '...finding' --- (2)
//
// 3초 후
// 'your name is 홍길동' --- (3)
// 'right?' --- (4)

promise를 이용해서 비동기 처리를 해보았습니다. (ㄱ)과 같이 promise에서 error를 던져주면 catch에서 잡아줘서 쉽게 error 체크를 해줄 수 있습니다.

 

async/await


결국 promise 도 연속적인 chaining을 하다 보면 콜백 지옥과 흡사해 지므로 좀 더 직관적인 async await가 나오게 되었는데요.  ES8 추가로 도입 되었습니다. Promise과 같이 then catch로 결괏값을 잡아내는 형식이 아닌 async await 동기적 코드처럼 작성이 가능합니다.

 

async function를 실행하면 promise 객체가 반환됩니다. 그리고 async function의 return 값은 promise의 resolve값이 됩니다. 

또한 async/await의 오류는 try/catch로 잡아 낼 수 있습니다.

 

await 키워드는 async function안에서만 사용할 수 있습니다. await는 promise 상태가 다 진행될 때까지 기다렸다가 다음으로 진행하게 됩니다. 그러므로 await 위치는 promise 객체를 생성하는 함수 앞에 놓입니다.

 

예제로 보여드리겠습니다.

const promise = function (id) {
	return new Promise((resolve, reject) => {
    	setTimeout(() => {
            const data = { 1: '홍길동', 2: '스펀지밥' };
            if (typeof id !== 'number') return reject(new Error("Id type is number!")); //--- (3)
            if (!data[id]) return reject("Sorry, I don't know you"); //---(3)
            resolve('your name is ' + data[id]); //---(3)
		}, 3000);
    });
}

async function findName(id) {
	try {
        console.log('what is your name?'); //--- (1)
       	console.log('...finding'); //--- (2)
        const finded = await promise(id);
        console.log(finded); //---(3)
    } catch (err) {
        console.log(err); //---(3)
    }
}

findName(1);

// 'what is your name?'
// '...finding'
// 
// 3초 후
// 'your name is 홍길동'

findName(3);

// 'what is your name?'
// '...finding'
// 
// 3초 후
// 'Sorry, I don't know you'

findName('a');

// 'what is your name?'
// '...finding'
// 
// 3초 후
// Error: Id type is number!

감사합니다!

반응형

댓글