Promise

han·2022년 1월 9일
0

콜백함수

자바스크립트 엔진은 알다시피 싱글쓰레드로 동작한다. 한데 ajax call이라던가, setTimeout 등 시간이 오래걸리는 일이 수행되어야 한다면, 이 일이 끝날때까지 뒤에 작업은 멈춰버리게 된다.
때문에 이러한 경우에는 함수를 미리 등록만 해두고, 어떤 일이 완료된 후 해당 함수가 실행되도록 해야 하는데, 이를 콜백함수라 한다.
콜백함수를 사용하여 순차적으로 수행되는 함수를 만들면 다음과 같다

const a1 = (func) => {
    setTimeout(() => {
        console.log('1');
        func();
    }, 2000);
}
const a2 = (func) => {
    setTimeout(() => {
        console.log('2');
        func();
    }, 3000);
}
a1(() => {
   a2(() => {
        console.log('end');
   }); 
});
1 // 2초 후
2 // 다시 3초 후
end

2개의 콜백함수의 중첩으로도 약간은 복잡해진다. 이걸 a1, a2, a3 ...함수로 더 깊게 들어가게 되면 그 유명한 '콜백지옥'이 된다.
뭐,, 예전에 이래서 힘들었단 얘기를 들어보긴 했지만 내가 겪어본 적은 없다.
이를 보완하기위해 promise나 async, await을 사용하기 때문인데 먼저 promise부터 적어본다.

Promise

Promise의 간단한 예제이다. promise 함수에 resolve와 reject라는 2개의 콜백함수를 등록해두었다.
성공 시 resolve가 불리고, 실패 시 reject가 불린다.

const a = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('success');
        // reject(new Error('fail'));
    }, 1000)
});
a.then((result) => {
    console.log(result);
}).catch((err) => { 
    console.log(err);   
}).finally(() => {
    console.log('end');
});

a는 promise 객체를 리턴받는데, 객체에는 state과 result가 있다. state은 pending이었다가 1초 후 성공 시 fulfilled가 되고 실패 시 rejected가 된다. result는 undefined였다가 전달받은 'success' 또는 Error 객체가 된다.
모든 수행이 끝나면 finally를 수행한다.
위 콜백함수에 대한 내용을 Promise를 사용할 경우 아래와 같다.

const a1 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success a1');
        }, 2000);
    })
}
const a2 = (data) => {
    console.log(data);
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('success a2');
        }, 3000);
    })
}
a1()
  .then((result) => a2(result))
  .then((result) => console.log(result))
  .finally(() => {
  	console.log('end');
});

결과는 동일하다.
이렇게 프로미스가 연결되는것을 promise chaining이라고 한다.
위 경우 a1에서 받아온 data를 a2에서 사용하고 있다. a1이 2초, a2가 3초, 총 5초가 걸리게 된다.
그런데 이렇게 앞에서 받아온 값을 사용해도 되지 않을경우, 즉 독립적으로 동작해도 상관없다면 이는 비효율적인 동작이 될 것이다.
병렬적으로 동작시키는 방법이 있다면 3초면 모두 완료가 될 것이다.
이를 지원하는 api가 Promise.all이다.

Promise.all([a1(), a2()]).then((result) => {
    console.log(result);
});
// 아래 결과값은 a2에있는 console.log(data)부분을 무시하고 작성하였다. 실제로는 undefined가 출력된다.
['success a1', 'success a2']

result에는 차례대로 결과값이 출력된다.
순서를 보장하며, 하나라도 실패 시 실패가된다.
참고) all 대신 race를 사용한다면 하나라도 완료하면 끝나게된다.

reference

https://www.youtube.com/watch?v=3Ao3OroqQLQ

0개의 댓글