Callback 과 Promise
자바스크립트에서 비동기 동시성 프로그래밍을 하는 방법으로는 크게 Callback과 Promise 가 있다.
function add10(a, callback){
setTimeout(()=>callback(a+10), 100)
}
100ms 이후에 받은 인자 a에 10을 더한 값을 콜백 함수에 전달 하였다.
add10(10, res=>{
log(res) // 100ms 이후 15 로깅
})
function add20(a){
return new Promise( resovle => setTimeout(()=>resolve(a+20), 100))
}
프로미스 에서는 함수에서 사용할 인자만 받고 콜백함수 같은건 받지 않는다. 여기서 중요한건 add20 함수에서는 프로미스 객체를 만들어서 리턴 하고 있다는 것 이다.
add(5)
.then(log) // 100ms 이후 25 로깅
여기서 잠깐..
add(5)
.then(result => log(result)) // 이거랑 then(log) 같구나
add20(5)
.then(add20)
.then(add20)
.then(add20)
.then(log)
프로미스는 그냥 then에 추가해주면 된다. 하지만 콜백함수는..
add10(10, res=>{
add10(10, res=>{
add10(10, res=>{
log(res)
})
})
})
인덴트 관리하기도 어렵고 보기 복잡한 부분이 있다.
3번에서 이야기 했던 것 처럼 프로미스는 콜백 보다 연속적인 실행관점에서 좀더 편하게 then, then, then 을 통해 값을 얻을 수 있다는 차이점이 있지만 정말 중요한 이 둘의 차이점은 프로미스는 비동기 상황을 일급으로 핸들링 한다는 것이다.
function add20(a){
return new Promise( resovle => setTimeout(()=>resolve(a+20), 100))
}
//비동기 상황을 코드로 해결
function add10(a, callback){
setTimeout(()=>callback(a+10), 100)
}
add10(10, res=>{
log(res)
})
function add10(a, callback){
setTimeout(()=>callback(a+10), 100)
}
let a = add10(10, res=>{
log(res)
})
log(a) // undefined
let b = add20(5).then(add20)
log(b) // Promise {<pending>}
...// 잠시 뒤
log(b) // Promise {<resolved> : 30}
let a = add20(5)
log(a) // Promise {<pending>}
...
log(a) // Promise {<resolved> : 25}
let b = a.then(c => c -5)
log(b) // Promise {<pending>}
...
log(b) // Promise {<resolved> : 20}
let d = b.then(log)
위와 같이 b 자리에 또 프로미스가 떨어지고 then을 작업을 이어갈 수 있다.
결론지으면 프로미스는 비동기 상황을 값으로 다룰 수 있고, 값으로 다룰 수 있다는 것( 코드로 다뤄지는게 아닌 )은 일급이라는 것이다. 일급이라는 이야기는 어떤 변수에 전달될 수 있고, 함수에 인자로 전달될 수 있고 전달 될 수 있다는 것은 어떤 작업을 계속해서 이어나갈 수 있다는 말이다.
Promise.resolve(Promise.rosolve(Promise.resolve(1))).then(log)
위와 같이 프로미스가 중첩되어 선언해 있다 하더라도 단 한번의 then 으로 안에 있는 결과를 꺼내서 볼 수 있다는 점이다.
Promise.resolve(Promise.resolve(1)).then(function(a){
log(a)
})
일반적으로 생각 해보면, then 함수 내부 function에는 Promise.resolve(1)
이라는 프로미스가 떨어질 것 같은데 그렇지 않고 프로미스가 아무리 깊게 있더라도 그 안쪽에 있는 값이 함수 내부에 떨어진다.
이말은 프로미스 체인이 연속으로 걸려 있어도 내가 원하는 곳에서 한번의 then으로 결과를 꺼내 볼 수 있다는 것이다. 마찬가지로
new Promise(resolve => resolve(new Promise( resolve1 => resolve1(1)))).then(log)
연속적으로 resolve를 하더라도 해당하는 결과는 한번의 then으로 꺼내 볼 수 있다.