[ES6] Promise함수(2)

권준혁·2020년 11월 1일
0

javascript

목록 보기
17/19
post-thumbnail

안녕하세요!

Promise함수에 대해 두 번째 포스팅해보겠습니다.
좀 더 다양한 활용방법에 대해 살펴보려고 합니다 !

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키워드를 사용해 작성합니다. (경우에 따라 예기치못한 버그가 발생할 수도 있다는 글을 본 적 있습니다.)


Promise.resolve의 반환값

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

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.all

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))
        // ...
    })
})
  1. funcObj객체를 외부에서 받아왔다고 가정합니다.
  2. Object.entries()로 2차원배열형태로 바꿉니다.
  3. map()함수로 내부 요소의 1번 index를 배열로 반환합니다.
  4. funcArr는 실행할 Promise함수를 담은 배열입니다.
  5. funcArr을 Promise.all의 인수로 사용합니다.

then()메서드의 인수로 배열비구조화로 각각 받을 수도 있습니다.

Promise.all(funcArr).then([first, second]=>{
    first().then(data => console.log(data))

})

Promise.all에서 인수로 Promise객체가 아닌 값을 넣으면 그대로 반환됩니다.


Promise.race

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가 출력됩니다.

이상으로 다양한 사용법에 대해 알아봤습니다!

profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글