본문 바로가기
코딩 공부/JavaScript

[JS] Promise

by 현장 2022. 11. 30.

Promise

프로미스는 자바스크립트 비동기 처리에 사용되는 객체로 비동기 함수 호출 또는 비동기 연산이 완료되었을 때, 이후에 처리할 함수나 에러를 처리하기 위한 함수를 설정하는 모듈입니다.

자바스크립트의 비동기 처리란?
‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성’을 의미합니다.

 

Promise가 필요한 이유

자바스크립트는 비동기 처리를 위해 콜백함수를 사용합니다. 하지만 콜백을 너무 남용하게 되면 우리가 흔히 부르는 콜백 지옥에 빠질 수가 있습니다.

콜백 지옥

또한 에러처리도 힘들 뿐더러 여러 개의 비동기 처리를 한번에 하는데 한계가 있습니다. 이런 콜백 함수의 단점을 보완하며 비동기 처리에 사용되는 객체를 프로미스(Promise)라 합니다.

콜백 함수란?
함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수

 

프로미스 사용시 이점

  • 비동기 처리 시점을 명확하게 표현할 수 있다.
  • 연속된 비동기 처리 작업을 수정, 삭제, 추가하기 편하고 유연하다.
  • 비동기 작업 상태를 쉽게 확인할 수 있다.
  • 코드의 유지 보수성이 증가한다.

Promise의 3가자 상태

프로미스를 사용할 때 알아야 하는 가장 기본적인 개념이 바로 프로미스의 상태(states)입니다. 여기서 말하는 상태란 프로미스의 처리 과정을 의미합니다. new Promise()로 프로미스를 생성하고 종료될 때까지 3가지 상태를 갖습니다.

1. Pending(대기)

비동기 처리 로직이 아직 완료되지 않은 상태입니다. 아래와 같이 new Promise() 메서드를 호출하면 대기(Pending) 상태가 됩니다.

new Promise();

new Promise() 메서드를 호출할 때 콜백 함수를 선언할 수 있고, 콜백 함수의 인자는 resolve, reject입니다.

new Promise(function(resolve, reject){
	// code
})

2. Fulfilled(이행)

비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태입니다. 여기서 콜백 함수의 인자 resolve를 아래와 같이 실행하면 이행(Fulfilled) 상태가 됩니다.

new Promise(function(resolve, reject){
	resolve();
})

그리고 이행 상태가 되면 아래와 같이 then()을 이용하여 처리 결과 값을 받을 수 있습니다.

function getData() {
  return new Promise(function(resolve, reject) {
    var data = "resolveValue";
    resolve(data);
  });
}

// resolve()의 결과 값 data를 resolvedData로 받음
getData().then(function(resolvedData) {
  console.log(resolvedData); //  "resolveValue"가 콘솔 로그에 찍힌다
});

3. Rejected(실패)

비동기 처리가 실패하거나 오류가 발생한 상태입니다.  reject를 아래와 같이 호출하면 실패(Rejected) 상태가 됩니다.

new Promise(function(resolve, reject){
	reject();
})

그리고, 실패 상태가 되면 실패한 이유(실패 처리의 결과 값)를 catch()로 받을 수 있습니다.

function getData() {
  return new Promise(function(resolve, reject) {
    reject(new Error("reject Error"));
  });
}

// reject()의 결과 값 Error를 err에 받음
getData().then().catch(function(err) {
  console.log(err); // Error: reject Error
});

Chained Promises

비동기 함수의 결과를 가지고 비동기 함수를 호출해야 하는 경우, 함수의 호출이 중첩되어 콜백 지옥이 발생할 수 있습니다. 하지만 프로미스는 후속 처리 메소드를 체이닝하여 프로미스를 반환하는 여러개의 비동기 함수들을 연결하여 사용할 수 있습니다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

 

function promise(result) {
    return new Promise(function(resolve, reject) {
        if(result == 'success')
            resolve('success')
        else
            reject('failed')
    })
}

promise('success')
    .then(promise) // .then(result => promise(result))
    .then(message => console.log('This is in the then ' + message))
    .catch(error => console.log('This is in the catch ' + error))

정적 메소드

정적메소드이기 때문에 객체의 생성없이 사용가능합니다.

1. Promise.resolve

결과값과함께 resolve된 Promise반환합니다.

2. Promise.reject

실패 원인과 함께 reject된 Promise 반환합니다.

3. Promise.all

프로미스가 담겨있는 배열과 같은 이터러블 객체를 인자로 받습니다. 인자로 전달받은 모든 프로미스를 병렬로 처리하고 그 결과값을 배열에 담아 resolve로 반환합니다. 모든 promise가 resolve될 때까지, 또는 한가지라도 reject될 때까지 기다립니다.

const promise1 = () => new Promise(resolve => setTimeout(() => resolve(1), 1000))
const promise2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000))
const promise3 = () => new Promise(resolve => setTimeout(() => resolve(3), 3000))

promise1().then(result => {
    console.log(result) // 프로그램을 실행하고 1초뒤에 수행됨
    return promise2()
}).then(result => {
    console.log(result) // 프로그램을 실행하고 3초뒤에 수행됨 (1 + 2)
    return promise3()
}).then(result => {
    console.log(result) // 프로그램을 실행하고 6초뒤에 수행됨 (1 + 2 + 3)
})

4. Promise.race

Promise.all 메소드와 동일하게 프로미스가 담겨있는 이터러블 객체를 인자로 받지만, Promise.all 과 달리 병렬로 처리하지 않고 가장 먼저 끝나는 프로미스의 결과값을 resolve로 반환합니다.

Promise.race([
    new Promise(resolve => setTimeout(() => resolve(1), 1000)),
    new Promise(resolve => setTimeout(() => resolve(2), 2000)),
    new Promise(resolve => setTimeout(() => resolve(3), 3000))
]).then(console.log) 
.catch(console.log)
// 가장 먼저 끝난 부분의 resolve의 data값이 1이므로 1출력

5. Promise.allSettled

Promise.all메소드와 동일하게 프로미스가 담겨있는 이터러블 객체를 인자로 받고 병렬로 처리합니다. 다만 Promise.all 의 경우 프로미스를 수행하던 도중 하나라도 에러(rejected)가 발생하면 rejected 상태가 되고 수행을 종료하게되지만, Promise.allSettled 메소드의 경우 rejected 상태가 되어도 수행을 종료하지않고, 프로미스가 수행된 상태와 결과값을 배열에 담아 resolve로 반환합니다.

Promise.allSettled([
    new Promise(resolve => setTimeout(() => resolve(1), 1000)),
    new Promise((resolve, reject) => setTimeout(() => reject(2), 2000))
]).then(console.log)
/*
    출력
    [
        { status: 'fulfilled', value: 1 },
        { status: 'rejected', reason: 2 }
    ]
*/

'코딩 공부 > JavaScript' 카테고리의 다른 글

[JS] Axios  (0) 2022.12.11
[JS] Fetch  (0) 2022.12.10
[JS] AJAX  (0) 2022.11.27
[JS] JSON  (0) 2022.11.23
[JS] JQuery  (0) 2022.11.14