개발 지식, 스크립트/JavaScript, TS

Promise- 후속 처리와 체이닝(Chaining)

개발하는지호 2023. 12. 10. 17:54

비동기 처리 수행 결과에 따른 후속 처리

resolve / reject 콜백에 의해 프로미스의 비동기 처리 상태가 변화하면 (pending -> fullfilled)

후속 처리를 수행할 코드를 작성해야 하는데 Promise 객체는 그러한 코드 작성을 할 수 있는 별도의 메소드를 제공한다.

 

then() , catch(), finally()

*후속 처리: 응답 결과 값 추출 or 사용

 

1. then(callback) - 비동기 처리 성공 시 호출

비동기 처리가 성공하여 resolve 콜백이 호출되었을 경우 동작하며, 실제 동작하는 것은 then() 이 아닌 then(callback) 함수의 인수로 전달된 콜백 함수이다.

1
2
3
const myPromise = new Promise(executor);
myPromise.then((response) => console.log(\`응답 결과: ${response}\`)); 
// 응답 결과: some data
cs

 

2. catch(callback) - 비동기 처리 실패 시 호출

비동기 처리가 실패하여 reject 콜백이 호출되었을 경우 동작하는 함수

1
2
3
4
5
6
const myPromise = new Promise(executor);
 
myPromise
.then((response) => console.log(\`응답 결과: ${response}\`))
.catch((error) => console.error(\`error: ${error}\`));
// error: 응답 실패
cs

 

3. finally(callback)

비동기 처리 성공/실패 여부와 상관없이 마지막에 한 번은 무조건 동작하도록 보장되는 함수

1
2
3
4
5
6
7
8
const myPromise = new Promise(executor);
 
myPromise
.then((response) => console.log(\`응답 결과: ${response}\`))
.catch((error) => console.error(\`error: ${error}\`));
.finally(() => console.log('요청 수행 완료'));
// 응답 결과: some data or error: 응답 실패
// 요청 수행 완료(무조건 한 번은 동작)
cs

 

프로미스 체이닝

아래와 같이 각각의 후속 처리 메서드들이 이어서 호출할 수 있도록 동작하는 이유는 해당 메소드들이 Promise 객체를 반환하기 때문이다.

1
2
3
4
5
6
7
8
onst myPromise = new Promise(executor);
 
myPromise
.then((response) => console.log(\`응답 결과: ${response}\`))
.catch((error) => console.error(\`error: ${error}\`));
.finally(() => console.log('요청 수행 완료'));
// 응답 결과: some data or error: 응답 실패
// 요청 수행 완료(무조건 한 번은 동작)
cs

 

프로미스 체이닝을 활용하여 콜백 헬 개선

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
onst url = '[https://jsonplaceholder.typicode.com'](https://jsonplaceholder.typicode.com');
const promiseGet = url => {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.send();
        xhr.onload = () => {
            if (xhr.status === 200) {
                // 응답 성공
                resolve(JSON.parse(xhr.response));
            } else {
                // 에러 처리
                reject(new Error(xhr.status));
            }
        };
    });
};
 
promiseGet(\`${url}/posts/1\`) // post id가 1번인 post 조회
    .then((user) => promiseGet(\`${url}/users/${user.userId}\`)) // 해당 post를 작성한 user의 id를 이용하여 user 정보 조회
    .then(userInfo => console.log(userInfo))
    .catch(error => console.error(error));
cs

-> then() 을 통해 별도의 들여쓰기 없이 연속적으로 비동기 처리 수행 가능

 

catch(callback)을 통해 에러처리가 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const url = '[https://jsonplaceholder.typicode.com'](https://jsonplaceholder.typicode.com');
const promiseGet = url => {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.send();
        xhr.onload = () => {
            if (xhr.status === 200) {
                // 응답 성공
                resolve(JSON.parse(xhr.response));
            } else {
                // 에러 처리
                reject(new Error(xhr.status));
            }
        };
    });
};
promiseGet(\`${url}/xxx/1\`) // 유효하지 않은 url로 조회 요청
    .then((user) => console.log(user))
   // .then(다른 비동기 처리 코드) ...
    .catch(error => console.error(error));
cs