이전 과제를 진행하던 중에 Promise라는 개념이 이미 몇 차례 등장했었는데 그때는 그때 당장 익혀야 할 다른 것들이 많아서 프로미스는 공부하지못했다. 나중에 다루게 될 개념이라고 들었기 때문에 이런 게 있구나 정도로 넘겼음. 하지만 자바스크립트에서 비동기 처리는 중요한 부분이기 때문에 이번에 정리를 해 둔다.
레퍼런스:
비동기 처리
자바스크립트의 비동기 처리란 특정 코드의 연산이 끝날 때까지 기다리지 않고 다음 코드를 먼저 실행하는 것.(non blocking)
비동기 처리의 예로는 setTimeout(), ajax 통신을 들 수 있다. 이런 특징은 코드를 실행하는 시간을 효율적으로 쓸 수 있지만, 실행되는 순서를 예측할 수 없다는 단점이 있다.
아래 코드의 결괏값은 A, B, C 가 순차적으로 나오지 않는다.
const printString = (string) => {
setTimeout(
() => {
console.log(string)
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A")
printString("B")
printString("C")
}
printAll() // 결과 값은?
의도한 순서대로 코드를 실행하기 위해서는 위의 코드에 콜백 인자를 넣어서 이렇게 수정할 수 있다.
const printString = (string, callback) => {
setTimeout(
() => {
console.log(string)
callback() //setTimeout 내에서 콜백 실행
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = () => {
printString("A", () => {
printString("B", () => {
printString("C", () => {})
})
})
}
printAll() // A B C가 순서대로 출력됨.
코드가 실행되는 순서를 원하는 대로 제어하기 위해 Callback을 활용할 수 있지만, 콜백 함수를 연속해서 사용할 때 콜백 지옥이 생길 수 있다. 웹이 고도화될수록 이런 연속적인 콜백이 필요하게 되었고, 이런 코드 구조는 가독성이 떨어지고 변경 등의 관리가 몹시 어렵다.
콜백 지옥의 해결책으로 등장하는 것이 Promise와 async & await.
Promise란?
프로미스는 자바스크립트 비동기 처리에 사용되는 객체를 말한다.
new Promise()로 프로미스를 생성하고 resolve()와 reject() 메서드를 통해서 다음 액션을 진행하거나, 에러 핸들링을 할 수 있다.
위의 콜백을 이용한 코드를 프로미스로 변경하면 더 가독성 좋은 코드를 작성할 수 있다.
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(
() => {
console.log(string)
resolve() //콜백대신 resolve
},
Math.floor(Math.random() * 100) + 1
)
})
}
const printAll = () => {
printString("A")
.then(() => {
return printString("B")
})
.then(() => {
return printString("C")
})
.then(() => {
return printString("D")
})
// ...
}
printAll() // A B C D 순서대로 출력됨
무엇보다 에러 핸들링을 할 때 콜백을 사용한 패턴에 비해 훨씬 편한 장점이 있다.
위의 코드에서 보듯이 프로미스는 .then 으로 여러 개의 프로미스를 연결하여 사용할 수 있다.
then() 메서드를 호출하고 나면 새로운 프로미스 객체가 반환되기 때문에 계속 연결해서 사용이 가능함. (Promise Chaining)
프로미스는종료될 때까지 3가지 상태(states)를 갖는데, 여기서 상태란 프로미스의 처리 과정을 의미한다.
-Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
-Fulfilled(이행): 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태
-Rejected(실패): 비동기 처리가 실패하거나 오류가 발생한 상태
점점 고도화되는 웹앱을 보면 비동기 처리 패턴은 앞으로도 더 많이 필요하게 될 것 같다.
많이 사용되는 패턴은 점점 더 단점을 보완한 코드를 작성할 수 있는 방법들이 나오게 마련이고 프로미스의 단점을 보완한 async & await가 등장하였으니,
Async & Await
비동기 함수를 async 함수로 만들기 위해서는 함수 앞에 async 키워드를 추가한다. async함수는 await키워드가 비동기 코드를 호출할 수 있게 해 준다. (await는 async함수 안에서만 쓸 수 있음. async함수를 실행하면 Promise를 반환함)
좋은 예시는 아니지만 위의 프로미스 코드에서 .then() 블록 대신 async & await를 사용해 보면,
일단 코드가 짧고, 왼쪽 정렬된 코드에서 순서를 한눈에 알 수 있고, 겹겹의 괄호들로 인한 혼잡함이 없다.
const printString = (string) => {
setTimeout(
() => {
console.log(string)
},
Math.floor(Math.random() * 100) + 1
)
}
const printAll = async () => {
await printString("A")
await printString("B")
await printString("C")
}
printAll() // A B C 순서대로 출력됨
예외처리 방식은 이어서 공부 후 추가 포스팅하기로!
'Coding > TIL (Today I Learned)' 카테고리의 다른 글
MySQL : connection 중복 이슈 (0) | 2020.04.05 |
---|---|
MySQL: SQL문 입력하다 ' 또는 `을 입력했을 때 (2) | 2020.04.02 |
ES6: Destructuring (구조분해 할당) (0) | 2020.02.13 |
CORS(Cross-Origin Resource Sharing) 에 관하여 (0) | 2020.01.27 |
브라우저는 어떻게 동작 할까 - Basic Web Architecture (0) | 2020.01.17 |