유튜브 동영상이 로딩되는 동안, 댓글을 달지 못하거나, 검색을 하지 못하는 등, 요청이 동기적으로 이루어진다면 매우 불편할 것이다. 갑자기 다른 동영상을 보고싶어 클릭을 해도 지금 영상이 완전히 로딩되지 않는다면 넘어갈 수 없기 때문이다. 하지만 단순한 비동기 처리는, 호출에 대한 처리가 랜덤으로 되는 일이 발생한다. 각 처리마다 걸리는 시간이 다르기 때문이다. 비동기에 대한 순서를 제어하는 방법들을 소개하겠다.
function printString(string){
setTimeout(() => {
console.log(string)
},
Math.floor(Math.random() * 100) + 1
}
function printAll() {
printString('a')
printString('b')
printString('c')
}
위 코드의 경우, setTimeout의 파라미터가 랜덤으로 들어가기 때문에, 각 알파벳이 순서대로 출력되지 않는다.
function printString(string, callback){
setTimeout(() => {
console.log(string)
callback()
},
Math.floor(Math.random() * 100) + 1
}
function printAll() {
printString('a', () => {
printString('b', () => {
printString('c', () => ())
})
})
}
위 코드의 경우, 인자에 콜백을 넣어 a를 출력하고 난 다음 printString('b')를 실행하기 때문에 a를 출력하는 데에 얼마나 걸리든 원하는 순서대로 출력을 낼 수 있다. 하지만 더 많은 함수를 순차적으로 실행시켜야 하는 경우 아래 그림과 같이 콜백지옥에 빠질 수 있다.
출처: https://adrianalonso.es/desarrollo-web/apis/trabajando-con-promises-pagination-promise-chain/
프로미스를 이용하여 위에서 본 콜백지옥에서 탈출할 수 있다. 프로미스 기반 비동기 함수를 호출하면, 해당 비동기 함수는 프로미스 객체를 반환한다. 프로미스 객체는 총 3가지 상태를 가지고 있다.
: 프로미스 인스턴스를 만만들어 resolve와 reject 콜백이 있는 콜백 함수를 인자로 넣어준다.
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(
() => {
console.log(string)
resolve()
},
Math.floor(Math.random() * 100) + 1
)
})
}
const printAll = () => {
printString("A")
.then(() => { //생성한 promise 사용
return printString("B")
})
.then(() => {
return printString("C")
})
}
printAll()
콜백 지옥을 빠져나오기 위해 사용하는 프로미스 또한, 반복이 되면 콜백 지옥과 같은 구조가 될 가능성이 있다. then
실행절에서 새로운 프로미스를 만들거나, then
절이 길어진다면 콜백 지옥과 다를 것이 없다. 이 문제를 해결하기 위해 Async
,Await
가 등장했다.
function makeCoffee(order){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
let coffee = `make ${order}`;
console.log(coffee);
resolve(coffee);
},
Math.floor(Math.random() * 100) + 1) // 임의의 값 생성
});
}
async function asyncGetCoffee(){
// 동기적으로 실행결과를 얻을 수 있다.
let americano = await makeCoffee('아메리카노');
let vanillaLatte = await makeCoffee('바닐라 라떼');
let einspanner = await makeCoffee('아인슈페너');
}
asyncGetCoffee();
Await
는 Async
함수 안에서만 사용할 수 있다.
Async & Await
에서 에러를 처리하는 방법은 크게 두 가지가 있다.