Promise를 소개하기 전, ES6 이전 비동기 처리에 사용하던 콜백 패턴에 대해 알아보자.
특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고
다음 코드를 먼저 실행하는 자바스크립트의 특성이다.
두번째 인자로 넘겨진 함수는 바로 실행되지 않고, 이벤트 리스너가 정의한 이벤트가 발행할 때 실행된다.
function onButtonClick() {
alert('click!')
}
document.querySelector('.button1').addEventListener('click', onButtonClick)
첫 번째 인자로 넘겨진 함수는 바로 실행되지 않고, setTimeout
혹은 setTimeout
의 시간만큼 지난 후에 실행된다.
function work() {
console.log('work!')
}
setTimeout(work, 1000)
setInterval(work, 3000)
console.log('work process')
work process
가 출력된 후 1초 후 work!
이 출력되고
이 후 3초마다 work!
이 출력된다.
데이터를 비동기로 요청하고, 요청 후의 동작을 비동기로 처리한다.
XHR의 예시는 아래 프로미스와 콜백을 비교하며 설명하겠다.
자바스크립트에서 비동기 처리를 위한 하나의 패턴은 콜백 함수를 사용하는 것이다.
처리 순서를 보장하기 위해 여러 개의 콜백 함수가 네스팅(nesting, 중첩)
되어 복잡도가 높아지는 것을 콜백 헬
이라고 부른다.
비동기 처리 모델은 실행 완료를 기다리지 않고 즉시 다음 task를 실행한다.
따라서 비동기 함수 내에서 처리 결과를 반환하면 기대한 대로 동작하지 않는다.
step1(function(value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
step5(value4, function(value5) {
// value5를 사용하는 처리
});
});
});
});
});
프로미스는 Promise
생성자 함수를 통해 인스턴스화한다.
Promise
생성자 함수는 비동기 작업을 수행할 콜백 함수를 인자로 전달받는데 이 콜백 함수는 resolve
와 reject
함수를 인자로 전달받는다.
// Promise 객체의 생성
const promise = new Promise((resolve, reject) => {
// 비동기 작업을 수행한다.
if (/* 비동기 작업 수행 성공 */) {
resolve('result');
}
else { /* 비동기 작업 수행 실패 */
reject('failure reason');
}
});
export function request(url, successCallback, failCallback) {
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', (e) => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
successCallback(JSON.parse(xhr.responseText))
} else {
failCallback(xhr.statusText)
}
}
})
xhr.addEventListener('error', (e) => failCallback(xhr.statusText))
xhr.open('GET', url)
xhr.send()
}
export function request(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', (e) => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.responseText))
} else {
reject(xhr.statusText)
}
}
})
xhr.addEventListener('error', (e) => reject(xhr.statusText))
xhr.open('GET', url)
xhr.send()
})
}
프로미스 코드를 살펴보면
Promise
생성자 함수는resolve
와reject
를 인자로 받아
비동기 작업에 성공하면
처리 결과를 전달하고
비동기 작업에 실패하면
reject 메소드를 호출한다.
callback hell
에서 벗어날 수 있다. Promise
로 정의된 작업끼리 연결할 수 있다.depth
가 크게 증가하지 않는다.