본문 바로가기
언어/Javascript, Typescript

[js] Promise 정리

by minhyeok.lee 2023. 3. 22.
반응형

Promise정리 [ State, Producer, Consumer(then, catch, finally), Promise Chaining, Error Handling ]

Promise란?

1. Promise는 비동기 작업에 대한 javascript 개체이다.

2. Promise는 State라는 상태값을 가지고 Promise 생상부분과 사용부분으로 나눌 수 있다.

3. 비동기 처리 동작은 기본적으로 callback과 동일하지만 단점(콜백지옥)을 보완했다.

 

1) State

state: pending -> fulfilled or rejected (보류 중 -> 이행 또는 거부됨)

pending 상태 = 값을 아직 알 수 없을 때 (data가 정확하게 할당되지 않았을 때 등)

fullfilled 상태 = 반환값이 할당되었을 때를 나타낸다.

rejected 상태 = 네트워크 에러같은 에러가 발생하였을 때를 나타낸다.

 

2) Producer, Consumer (생산자 vs 사용자) 아래 참고.

 




1. producer (생산자)

new Promise가 생성되면 executor(실행자)가 자동으로 실행된다

executor는 성공할 때 실행하는 resolve와 실패할 때 실행되는 reject가 존재한다.

 

resolve 실행 시

const promise = new Promise((resolve, reject) => {
  // 네트워크를 통한 데이터 수신, 파일 읽기와 같은 시간이 걸리는 일을 수행한다.
  console.log('doing something...');
  setTimeout(() => {
  	resolve('success'); // 성공 시 호출
    }, 2000);
});

promise.then((value) => {
  console.log(value);
})

2초후에 Promise에서 성공할 때 호출하는 resolve가 실행된다.

 

출력값

success

 

reject 실행 시

const promise = new Promise((resolve, reject) => {
  // 네트워크를 통한 데이터 수신, 파일 읽기와 같은 시간이 걸리는 일을 수행한다.
  console.log('doing something...');
  setTimeout(() => {
    reject(new Error('no network')); // 실패 시 호출
    }, 2000);
});

promise.then((value) => {
  console.log(value);
})

2초후에 Promise에서 실패할 때 호출하는 reject가 실행된다.

 

출력값

 - 에러 발생 시 예외처리를 하지 않아 에러 창이 나온다.

 



2. Consumers (사용자): then, catch, finally

promise
  .then((value) => {
  console.log(value);
  })
  .catch(error => {
    console.log(error);
  })
  .finally(() => { console.log('finally'); });

then()는 promise가 정상적으로 수행되어서 resolve라는 콜백함수에서 전달한 값이 value의 parameter로 전달된다.
catch()는 실패해서 resolve 대신에 reject가 호출될 때 사용한다. (Error 핸들링 방법)
finally()는 성공여부에 상관없이 실행하는 함수이다.

 

출력값

// 성공시
"success"
"finally"

// 실패시
no networkError
"finally"

 


 

3. Promise chaining

const fetchNumber = new Promise(resolve, reject) => {
    setTimeout(() => resolve(1), 1000);
});
 
 
 fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
  return new Promise(resolve, reject) => {
    setTimeout(() => resolve(num - 1), 1000);
    });
})
.then(num => console.log(num));

위 코드는 2초 후에 5가 나온다.
여기서 알 수 있는 점은 then()은 값을 바로 전달할 수도 있고 Promise를 전달할 수도 있다.

 


 

4. Error Handling

const getA = () => 
  new Promise((resolve, reject) => 
    {setTimeout(() => resolve(`A`), 1000)
  });

const getB = A => 
  new Promise((resolve, reject) => 
    {setTimeout(() => resolve(`${A} => B`), 1000)
  });

const getC = B => 
  new Promise((resolve, reject) => 
    {setTimeout(() => resolve(`${B} => C`), 1000)
  });

위와 같은 코드가 존재한다.

 

아래의 두 코드는 동일하게 동작한다.

getA()
  .then(A => getB(A))
  .then(B => getC(B))
  .then(ABC => console.log(ABC));

getA() //
  .then(getB)
  .then(getC)
  .then(console.log);

단 하나의 값을 전달하고 받을 때는 위 코드처럼 생략이 가능하다.

두 번째 getA()에 // 주석이 존재하지 않으면 prettier에 의해 한 줄로 바뀌게 된다. 

 

아래는 Error 핸들링 방법이다.

// getB에서 Error가 발생되었을 때
const getB = A => 
  new Promise((resolve, reject) => 
    {setTimeout(() => reject(new Error(`error! ${A} => B`)), 1000)
  });

  
getA() //
  .then(getB)
  .catch(error => {
  	return 'b';
  })
  .then(getC)
  .then(console.log)
  .catch(console.log);

위 코드처럼 then() 중간중간에 .catch()를 걸어 세밀하게 ErrorHandling이 가능하다.

 


 

Promise 사용시 주의사항

 

1. Promise는 선언 시에 그 값을 요청하고 받아오기 때문에 사용하지 않는 값을 가져올 수도 있다.

2. Cunsumer의 요구 사항에 따라 netNetworkConnect 가져와야 한다.

3. 누군가 요구하지 않았는데 통신이 이어지게 하면 자원이 낭비될 수 있다.

반응형

댓글