Posts Promise
Post
Cancel

Promise

Promise 는 ES6 에서 추가되었으며, 자바스크립트의 비동기 작업을 처리하기 위해 사용한다.

</br>

기존의 자바스크립트에서는 비동기 작업을 처리하기 위해 콜백 방식을 사용하고 있었다. 하지만 콜백 방식은 여러 단계의 비동기 작업을 처리하는 경우 콜백에서 콜백을 호출하는 코드가 반복되면서 관리가 복잡해지고, 에러 핸들링이 필요한 경우 각 콜백에서 또 다시 콜백으로 처리를 해주어야 했다.

</br>

Callback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
doSomething(function (result) {
    doSomethingElse(
        result,
        function (newResult) {
            doThirdThing(
                newResult,
                function (finalResult) {
                    console.log('Got the final result: ' + finalResult);
                },
                failureCallback,
            );
        },
        failureCallback,
    );
}, failureCallback);

</br>

Promise 는 기존의 콜백 방식에 비해 다음과 같은 이점을 가지고 있다.

</br>

  • 코드의 가독성 향상
  • 비동기 작업 처리 개선
  • 비동기식 로직의 제어 흐름 개선
  • 향상된 에러 핸들링

</br>

Promise

1
2
3
4
5
6
7
doSomething()
    .then((result) => doSomethingElse(result))
    .then((newResult) => doThirdThing(newResult))
    .then((finalResult) => {
        console.log(`Got the final result: ${finalResult}`);
    })
    .catch(failureCallback);

</br>

사용 방법

</br>

Promise 객체는 생성자를 이용하여 생성할 수 있으며 resolve, reject 함수를 파라미터로 갖는 executor 함수를 인자로 구현해주어야 한다. 새로운 Promise 객체가 생성되면 그 객체는 대기(pending) 상태가 된다.

</br>

Promise 객체를 생성하는 순간 executor 함수가 실행되기 때문에 Promise 를 사용하는 시점에서 객체를 생성하고 실행하기 위해 함수에서 새로운 Promise 객체를 생성하여 리턴하는 방식이 주로 사용된다.

</br>

1
2
3
4
5
6
7
8
const doSomething = () => {
    return new Promise((resolve, reject) => {
        //비동기 처리를 위해 setTimeout 함수를 사용
        setTimeout(() => {
            resolve('success');
        }, 0);
    });
};

</br>

Promise 내에서 작업의 완료와 거부는 executor 함수의 파라미터인 resolve, reject 함수를 이용한다.

</br>

resolve / then

작업이 성공적으로 완료될 경우 resolve 함수를 호출해주면 되는데, 콜백에서 사용할 데이터를 인자로 넣어줄 수 있다. resolve 함수가 호출되면 이행(fulfilled) 상태가 된다.

</br>

resolve 호출의 콜백은 then 에서 구현한다.

</br>

1
doSomething().then((res) => console.log('Response data : ', res));

</br>

여러 단계로 체이닝이 가능하며 return 된 데이터는 다음 콜백에서 사용할 수 있다.

</br>

1
2
3
4
5
6
doSomething()
    .then((result) => doSomethingElse(result))
    .then((newResult) => doThirdThing(newResult))
    .then((finalResult) => {
        console.log(`Got the final result: ${finalResult}`);
    });

</br>

reject / catch

</br>

반대로 작업이 어떠한 이유로 실패하는 경우 reject 함수를 호출해주면 되고, 마찬가지로 콜백에서 사용할 데이터를 인자로 넣어줄 수 있다. reject 가 호출되면 거부(rejected) 상태가 된다.

</br>

reject 호출의 콜백은 catch 에서 구현한다.

</br>

1
2
3
doSomething().catch((err) => {
    console.error(err);
});

</br>

Error handling

</br>

Promise 의 에러핸들링은 reject 와 마찬가지로 catch 콜백에서 구현하여 사용할 수 있다.

</br>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const doSomthing = () =>
    new Promise((resolve, reject) => {
        //존재하지 않는 객체의 forEach 함수를 호출하면서 오류가 발생한다.
        notExistArray.forEach((element) => console.log(element));
        resolve();
    });

doSomthing()
    .then(() => console.log('Success'))
    .catch((err) => {
        console.error('Unexpected error occurred\n', err);
    });

/*
Unexpected error occurred
ReferenceError: notExistArray is not defined
    at ....
*/

</br>

여러개의 콜백 체인을 형성한 경우에도 에러가 발생한 위치와 상관없이 catch 콜백으로 에러 핸들링이 이루어진다.

</br>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const doSomthing = () =>
    new Promise((resolve, reject) => {
        resolve();
    });

doSomthing()
    .then(() => console.log('First'))
    .then(() => {
        throw new Error('Error occurred in second callback');
    })
    .then(() => console.log('Third'))
    .catch((err) => {
        console.error('Unexpected error occurred\n', err);
    });

/*
First
Unexpected error occurred
Error: Error occurred in second callback
    at ...
*/

</br>

참고자료

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Using_promises

https://www.geeksforgeeks.org/javascript-promises/

This post is licensed under CC BY 4.0 by the author.

이벤트 루프

Promise와 이벤트 루프

Comments powered by Disqus.