
자바스크립트에서는 비동기 처리를 하기 위해 콜백 함수를 사용한다. 하지만 전통적인 콜백 패턴은 콜백 지옥으로 빠질 위험이 있다. 이러한 콜백 패턴을 보완하기 위해 ES6에서는 Promise를 도입했다.
Promise는 비동기 작업을 처리하기 위해 도입된 객체다. 이 객체에는 어떠한 작업에 대한 결과가 담겨있다. Promise 생성자 함수는 비동기 처리를 수행할 골백 함수를 인수로 전달 받는데 이 콜백 함수는 resolve와 reject 함수를 인수로 전달받는다. 이동기 처리가 성공하면 resolve, 실패하면 reject 함수를 호출한다.
promise는 비동기 처리가 어떻게 진행되고 있는지를 나타내는 상태 정보를 갖는다.
promise는 기본적으로 pending 상태다. 이후 비동기 처리가 수행되면 비동기 처리 결과에 따라 다 상태가 변경된다.
promise는 후속 메서드로 then, catch, finally를 제공한다.
then은 JavaScript Promise 객체에서 비동기 작업이 성공적으로 완료되었을 때 실행할 동작을 정의하는 메서드다. 이 메서드는 Promise가 fulfilled 상태가 되었을 때 호출되며, resolve로 전달된 값을 처리한다.
then 메서드는 두 개의 콜백 함수를 매개변수로 받을 수 있다.
promise.then(onFulfilled, onRejected);
resolve(value)로 전달된 값을 인수로 받음.reject(reason)로 전달된 실패 이유를 인수로 받음.catch는 Promise 체인에서 실패를 처리하기 위한 메서드다.
Promise가 rejected 상태가 되거나, 체인 중간에서 에러가 발생한 경우 호출된다.
promise.catch(onRejected);
finally는 Promise의 성공 또는 실패 여부와 상관없이 항상 실행되는 메서드다.
리소스를 정리하거나, 공통적으로 실행해야 할 작업을 정의할 때 유용하다.
promise.finally(onFinally);
JavaScript에서 프로미스 체이닝은 여러 개의 then 메서드를 연결하여 비동기 작업을 순차적으로 처리하는 방법이다.
이를 통해 비동기 작업을 읽기 쉽고 관리하기 편리한 코드로 작성할 수 있다.
프로미스 체이닝은 then 메서드를 여러 번 연결하여 비동기 작업이 완료된 후 다음 작업을 실행하는 방식이다.
각각의 then 메서드는 이전 then의 반환값을 전달받아 작업을 처리한다.
프로미스는 프로미스 체이닝을 통해 비동기 처리 결과를 전달받아 후속 처리를 하므로 비동기 처리를 위한 콜백 패턴에서 발생하던 콜백 헬이 발생하지 않는다. 다만 프로미스도 콜백 패턴을 사용하므로 콜백 함수를 사용하지 않는 것은 아니다.
promise
.then(onFulfilled1)
.then(onFulfilled2)
.then(onFulfilled3)
.catch(onRejected);
Promise.all은 여러 개의 프로미스를 병렬로 처리하고, 모든 프로미스가 성공적으로 완료될 때까지 기다린 후 결과를 반환하는 메서드다.
이 메서드는 주어진 프로미스들이 모두 fulfilled 되었을 때 하나의 Promise를 반환하며, 모든 프로미스가 완료되면 그 결과들을 배열로 반환한다. 인수로 전달 받은 배열의 프로미스가 하나라도 rejected 상태가 되면 나머지 프로미스가 fulfilled 상태가 되는 것을 기다리지 않고 즉시 종료한다.
const requestData1 = () => new Promise(resolve => setTimeout(() => resolve(1), 3000));
const requestData2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000));
const requestData3 = () => new Promise(resolve => setTimeout(() => resolve(3), 1000));
Promise.all([requestData1(), requestData2(), requestData3()])
.then(console.log) // [ 1, 2, 3 ] ⇒ 약 3초 소요
.catch(console.error);