안녕하세요!
이번포스팅에서는 자바스크립트 빌트인 객체 Promise에대해 알아보겠습니다.
- Promise
동기식은 순서가 정해져있고 하나가 완료되면 다음순서가 진행되는 식입니다
비동기는 준비가 완료되는 것 부터 실행하기때문에 동시에 실행될 수 있습니다.
비동기의 가치는 처리중인 지연된 정보를 기다리는동안 다른 코드를 또 실행할 수 있다는 점입니다. API응답을 기다리는동안 사용자는 다른 요청을 할 수 있습니다.
이 전 자바스크립트에서는 callback을 이용한 비동기를 만들었지만,
callback의 깊이가 조금만 깊어져도 코드가 지저분해지는 등의 문제점으로 인해
Promise가 등장했습니다.
Promise는 비동기를 위한 객체입니다.
new Promise(executor)
executor는 resolve 및 reject 인수를 전달할 실행 함수입니다.
function checkLength (param) {
return new Promise((resolve,reject)=>{
if(param.length < 10) {
resolve(param) // param을 전달합니다 chain에서 .then()을 이용해 호출할 수 있습니다.
}else{
reject(new Error('too long')) // error을 전달합니다 chain에서 .catch()를 이용해 호출할 수 있습니다.
}
})
}
checkLength는 param을 인수로 받아 Promise객체를 반환합니다.
param.length가 10미만이면
resolve(param)으로 정상적으로 전달합니다.
아닐 경우에는 Error를 너무 길다는이유와 함께 반환합니다
이런 형태의 함수들을 Promise를 통해 선택적으로 연결 할 수 있습니다.
Promise는 다음 중 하나의 상태를 가집니다.
기본 전달값이 아무 것도 하지 않았으면 'value'는 'undefined'입니다.
직접 한 번 만들어보겠습니다.
function devideByTwo (num) { // 2로 나눈다
return new Promise((resolve,reject)=>{
if(isNaN(num)){
reject(new Error('Not a Number'))
}else{
resolve(num/2)
}
})
}
function MultiplyByThree (num) { // 3을 곱한다
return new Promise((resolve,reject)=>{
if(isNaN(num)){
reject(new Error('Not a Number'))
}else{
resolve(num*3)
}
})
}
function AddFive(num) { // 5를 더한다
return new Promise((resolve,reject)=>{
if(isNaN(num)){
reject(new Error('Not a Number'))
}else{
resolve(num+5)
}
})
}
function SubtractFour(num) { // 4를 뺀다
return new Promise((resolve,reject)=>{
if(isNaN(num)){
reject(new Error('Not a Number'))
}else{
resolve(num-4)
}
})
}
function printLog(num) { // 로그에 출력한다.
console.log(num)
return new Promise((resolve,reject)=>{
resolve(num)
})
}
다섯 개의 함수를 만들어봤습니다. 각각 사칙연산을 하고 나머지 한 개의 함수는 로그에 출력합니다.
Promise를 이용하는 함수를 만들 때는 Promise객체를 반환해야 한다는 것을 염두하고 있어야합니다.
return값은 아래코드의 return값처럼 바꿀 수도 있습니다.
function printLog(num) {
console.log(num)
return Promise.resolve(num) // 이 부분
}
Chaining 해보기
const fifteen = 15
AddFive(15) // 15+5
.then(MultiplyByThree) // 20*3
.then(devideByTwo) // 60/2
.then(SubtractFour) // 30-4
.then(AddFive) // 26+5
.then(printLog) // 31
.catch(err => console.log(err))
Promise는 두 개의 인수 resolve()와 reject()를 전달받고, 코드가 의도대로 동작됐을 때 resolve()가 실행됩니다. resolve()가 호출되면 then()메서드에 전달된 함수가 실행됩니다.
확실히 Promise의 then으로 Chaining하게되면 보기가 편합니다.
여기에서는 숫자를 단순하게 사칙연산을 수행하는 Promise를 만들어봤지만
각각의 함수가 다른역할을 수행하고 Chaining으로 연결할 수 있다는점, 순서가 지켜진다는 점이 장점입니다
.then(함수)의 순서를 임의로 바꿔서 필요할때마다 적용할 수 있습니다.
지난 게시물에서 자바스크립트는 싱글스레드로 컨텍스트를 Stack구조로 관리한다고 했었습니다.
콜백이 값을 반환하기를 기다리는 동안 JS 엔진의 나머지 스택은 계속 실행되기 때문에 자바 스크립트가 비동기 적으로 작동합니다.
const original = Promise.resolve(33);
const cast = Promise.resolve(original);
cast.then(function(value) { // (1)
console.log('value: ' + value);
});
console.log('original === cast ? ' + (original === cast)); // (2)
//result
original === cast ? true
value: 33
(1)번 Promise메서드가 2번 log메서드보다 위에 있는데도 늦게 출력됩니다.
(1)번 메서드가 Stack에서 지워지고 이벤트큐에 갔다오는 동안 (2)번 log메서드가 출력되기 때문입니다.
읽어주셔서 감사합니다!!