javascript 애플리케이션은 단일 스레드에서 동작합니다. 즉, 한 번에 한 가지 일만 할 수 있죠. 여러 가지 일을 동시에 하지 못하는 대신 다른 부수 효과(side effect)에서 자유로울 수 있다는 장점이 있습니다. 하지만 부드러운 자바스크립트 애플리케이션을 만들기 위해서 비동기적 관점이 필요합니다. 이를 좀 더 쉽게 개발자들이 접근할 수 있도록 비동기적 프로그래밍에 필요한 장치들이 추가되었습니다. 이 장치들을 지금부터 알아보겠습니다.
콜백 함수
를 넘겨 줍니다.const timeout = 3 * 1000
console.log('start!')
console.log('=============== (1)')
setTimeout(() => {
console.log('end!', new Date())
}, timeout)
console.log('=============== (2)')
// [ result ]
// start!
// =============== (1)
// =============== (2)
// end! 2019-11-11T07:00:49.645Z
// setTimeout의 로그는 정상적인 시간에 잘 찍힙니다. 하지만 i는 계속 -1로 찍힙니다.
// 이는 setTimeout 자체는 동기적으로 실행됨을 의미합니다. 단지, 콜백으로 넘겨준 함수는 비동기적으로 호출되지요.
// i가 for문 밖에 있기 때문에, setTimeout의 익명함수의 i를 모두 공유하게 됩니다.
// 따라서 연산이 다 끝난 -1이 찍힐 수 밖에 없습니다.
// 우리가 원한대로 5,4,3,2,1,GO가 찍힐 수 있게 하기 위해선 countdown2 함수처럼 수정해야합니다.
function countdown1() {
let i
for (i = 5; i >= 0; i--) {
setTimeout(() => {
console.log(i === 0 ? 'GO' : i)
}, (5 - i) * 1000)
}
}
countdown1()
// -1
// -1
// -1
// -1
// -1
// -1
function countdown2() {
for (let i = 5; i >= 0; i--) {
setTimeout(() => {
console.log(i === 0 ? 'GO' : i)
}, (5 - i) * 1000)
}
}
countdown2()
// 5
// 4
// 3
// 2
// 1
// GO
프라미스(promise)
가 등장하였습니다.$.get('url', function(response) {
parseValue(response, function(id) {
auth(id, function(result) {
display(result, function(text) {
console.log(text)
})
})
})
})
위에서 언급한 내용처럼 프라미스는 콜백의 단점을 보완하기 위해 만들어졌습니다. 콜백을 대체하는 개념보다는 콜백을 활용하여, 개발자들이 예측할 수 있는 패턴을 만들었다고 이해하는 것이 좋습니다.
성공(fulfilled)
혹은 실패(rejected)
만 합니다. 그외는 결과는 절대 없습니다. 즉, 두 가지 상황만 기대할 수 있고, 그에 따른 처리 로직을 작성해주시면 됩니다.resolve(성공)
과 reject(실패)
콜백이 있는 함수로 새 Promise 인스턴스를 만들기만 하면 됩니다.function countdown(seconds) {
return new Promise(function(resolve, reject) {
for (let i = secondes; i >= 0; i--) {
setTimeout(function() {
if (i > 0) console.log(i + '...')
else resolve(console.log('Go!'))
}, seconds * i * 1000)
}
})
}
countdown(5)
.then(() => {
// 성공한 다음 해야할 로직
})
.catch(err => {
// 실패(에러 등) 후, 해야할 로직
})