안녕하세요!
Promise함수에 대해 두 번째 포스팅해보겠습니다.
좀 더 다양한 활용방법에 대해 살펴보려고 합니다 !
const p1 = new Promise((resolve,reject)=>{
// ....
})
const p2 = Promise.resolve(data);
const p3 = Promise.reject('error Message')
p1의 경우, 함수 내부에서 비동기 작업 실행 후 성공,실패에 따라 resolve또는 reject함수를 호출하면 됩니다.
p2는 Promise객체가 인수라면 그 객체가 그대로 반환되고, 아니라면 이행됨 상태의 프로미스가 반환됩니다.
p3는 거부됨 상태의 프로미스가 생성됩니다.
일반적으로 new키워드를 사용해 작성합니다. (경우에 따라 예기치못한 버그가 발생할 수도 있다는 글을 본 적 있습니다.)
const p1 = Promise.resolve(123);
console.log(p1 === 123) // false
console.log(p1 !== 123) // true
console.log(p1 === Promise.resolve(123)) // false
console.log(p1 === Promise.resolve(p1)) // true
Promise.resolve함수에 Promise가 입력되면 자신이 반환됩니다.
finally는 2018년 JS표준으로 채택됐습니다. finally()는 이 전에 사용된 프로미스를 그대로 반환합니다. 새로운 Promise를 생성하지 않습니다. 처리된 상태의 Promise를 건드리지 않고 추가적인 작업을 실행할 때 유용합니다.
function requestData() {
return fetch()
.catch(err => {
console.log(err)
}).finally(()=>{
sendLogToServer('requestData finished') // 서버로 보고
})
}
requestData.then(data => console.log(data))
finally는 이전의 Promise객체를 건드리지 않기 때문에 finally를 신경 쓰지 않아도 됩니다. 그저 Promise객체와 상관 없이 비동기작업마다 수행해야 하는 작업을 finally에 작성하면됩니다.
Promise를 반환하는 작업이 두개가 있다고 가정하겠습니다.
requestData1().then(data=>console.log(data))
requestData2().then(data=>console.log(data))
다음 코드는 병렬로 실행됩니다.
이런 경우 Promise.all로 코드를 줄일 수 있습니다.
이 중 하나라도 거부된다면 Promise.all이 반환하는 함수는 거부됨 상태가 됩니다.
Promise.all([requestData1(),requestData2()]).then(([first,second])=>{
console.log(first)
console.log(second)
})
만약에 Promise함수를 다른 모듈에서 받아서 이름을 모르는 상태로 동적으로 사용해야 한다면?
(이런 경우는 별로 없을 것 같지만, Promise.all이 Promise객체를 배열로 받는 다는 것을 확인해보겠습니다.)
외부모듈에서 JSON형태로 내부요소가 함수인 객체를 받아왔다고 가정하겠습니다.
const funcObj = { // 이 것을 외부모듈에서 받는다면?
requestData1() {
return new Promise((resolve,reject)=>{
resolve('data1')
})
},
requestData2() {
return new Promise((resolve,reject)=>{
resolve('data2')
})
}
}
const funcArr = Object.entries(funcObj).map(item=> item[1])
Promise.all(funcArr).then(res=>{
res.forEach(elem => {
elem().then(data=>console.log(data))
// ...
})
})
then()메서드의 인수로 배열비구조화로 각각 받을 수도 있습니다.
Promise.all(funcArr).then([first, second]=>{
first().then(data => console.log(data))
})
Promise.all에서 인수로 Promise객체가 아닌 값을 넣으면 그대로 반환됩니다.
Promise.race는 여러 개의 프로미스들 중 가장 빨리 처리된 Promise를 반환합니다. 여러 Promise들 중 하나라도 처리됨 상태가 되면 Promise.race가 반환하는 함수도 처리됨 상태가 됩니다.
const limitRequestData = (second) => new Promise((resolve,reject)=>{
const time = second*1000
setTimeout(()=>{resolve('data')},time)
})
const causeError = new Promise((resolve,reject)=> setTimeout(reject,3000))
Promise.race([
limitRequestData(4), // (★)
causeError
])
.then(data => console.log(data))
위 코드에서는 limitRequestData 와 causeError함수가 Promise.race의 인수로 들어갔습니다.
두 함수는 각각 setTimeout으로 시간이 설정돼 있습니다.
3초내에 limitRequestData가 resolve되면 Error를 반환하지 않습니다.
(★)에서 함수의 인수로 1또는 2를 넣으면 로그에 data가 출력됩니다.
이상으로 다양한 사용법에 대해 알아봤습니다!