What it promise? / TIL 2021.06.10~11

leitmotif·2021년 6월 10일
0

🧐 Promise?

📂 개요

어떤 작업에 대한 상태 정보를 가지고 있는 객체.
fetch(), ajax 등의 통신 코드가 프로미스 객체를 가지고 온다.

Pending ... 진행 중
Fulfilled... 성공
Rejected ... 실패

Fulfilled 상태에서 promise는 작업 성공 결과를 포함한다.
Rejected 상태에서 작업 실패 결과를 포함한다.

fetch('url')
.then((res)=>res.text()) 
.then((result) => {console.log(result);});

위의 코드에서, Response가 수행됐다면 Fulfilled 상태가 된다.
이 때 then에 해당하는 callback 함수가 수행된다.

fetch('url')
.then((res)=>res.text() , (error) => {console.log(error);}) 
.then((result) => {console.log(result);});

위처럼 rejected 상태일 때 실행될 콜백 함수를 작성할 수 있다.

단순히 2번째 파라미터에 error를 표시할 객체를 넣어주면 되고..
변수명은 아무래도 상관없겠지만 error가 가장 편할 것 같다.

📂 Promise chaining

fetch('url')
.then((res)=>res.text()) 
.then((result) => {})
.then((~) =>{})
.then((~) =>{})
......

위와 같이 then method를 계속 연결짓는 것을 Promise Chaining이라고 한다.

비동기적인 작업을 순차적으로 처리하는 데에 목적이 있다.

  1. callback 함수에서 promise 객체를 반환하는 경우
    then 함수에서 반환한 promise 객체와 동일한 상태와 결과를 가진다.
  2. callback 함수에서 단순 숫자, 문자열 등을 반환하면
    then 함수의 promise는 fulfilled가 되면서 성공 결과는 반환된 값이 된다.

res.text(), json()은 값만 가져오는 것이 아닌 Promise obj를 리턴한다.

따라서 리턴된 Promise 객체에서 체이닝이 시작된다고 생각했을 때
response 이후의 then함수에 원하는 값이나 객체를 사용해 작업을 할 수 있다.


fetch 함수를 중심으로 promise 개념을 공부했다.

각각 함수의 반환 값을 통해서 작업을 처리하는 것이 인상깊었는데,

if~else가 무한정 중첩되는 그런 현상을 Promise로 커버할 수 있을 것 같다.


📂 사용자 정의 Promise

const p = new Promise((resolve, reject) =>{
	setTimeout(() => {resolve('success');},2000);
}); 

// p가 fulfilled가 되고, resolve의 success가 성공 결과로 저장된다.

p.then((result)=>{ console.log(result); });
// p의 내용에 맞게 2초 후 success가 출력된다.

const p2 = new Promise((resolve, reject) =>{
	setTimeout(() => {reject(new Error('fail'));},2000);
}

p2.catch((error) =>{console.log(result);});

// p2는 에러를 발생시켜 rejected가 된다.
// 2초 후 Error : fail이 출력된다.
// 따라서 then이 아닌 catch를 이용해 출력하도록 했다.

평소에는 임의로 정의한 Promise가 사용되지 않으나, Promisify를 진행할 때 사용된다.

비동기 실행 함수, setTimeout같은 함수를 Promise 객체로서 반환하는 것을 Promise화 하다, Promisify라고 한다.

function wait(text, milliseconds) {
  const p = new Promise((resolve, reject) => {
    setTimeout(() => { resolve(text); }, 2000);
  });
  return p;
}

fetch('https://jsonplaceholder.typicode.com/users')
  .then((response) => response.text())
  .then((result) => wait(`${result}`, 2000)) 
  .then((result) => { console.log(result); });

일반적인 동기 함수에 불과했다면 return 값이 없어 undefined가 출력됐을테지만

위와 같이 Promise 객체화하여 잘 표시되도록 할 수 있다.


📂 Promisify의 주의점

Promise 객체에 값이 한 번 저장되면 변경되지 않는다.
따라서 callback이 한 번만 실행되면 되는 경우에만 Promisify를
하자.
포함하여, 여러 번 상호작용되도록 만든 Event에 주의할 것.


📂 Promise의 부가적인 함수들

1. all

const p1 = fetch(url).then((res)=>res.json());
const p2 = fetch(url).then((res)=>res.json());
const p3 = fetch(url).then((res)=>res.json());

Promise
	.all([p1,p2,p3])
    .then((result) => {
    	console.log(result);
    })
    .catch((error) => {
    	console.log(error);
    });

all 메서드를 이용해 여러가지 프로미스 객체를 다룰 수 있다.
단, 하나의 프로미스 객체가 rejected가 되면 전체 작업이 실패된 것으로 간주된다.

2. race

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Success'), 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('fail')), 2000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('fail2')), 4000);
});

Promise
  .race([p1, p2, p3])
  .then((result) => {
    console.log(result); 
  })
  .catch((value) => {
    console.log(value);
  });

race 함수는 all과 사용법은 같지만 각 Promise 객체 중 가장 빨리 결정된 객체의 상태와 결과를 가진다.

위의 코드는 p1이 제일 빨리 결정되므로,
Promise는 fulfilled 상태가 되며 성공 결과인 'Success'가 출력된다.

3. allSettled

const promise1 = Promise.resolve('success');
const promise2 = new Promise((resolve,reject) 
			=>setTimeout(reject, 100, 'foo'));

Promise.allSettled([promise1,promise2])
.then((result) => result.forEach((result) => console.log(result.status)));

allSettled 함수는 전달된 Promise 객체들의 상태와 value 쌍을 가진다.
위의 코드에서는 status를 출력했으므로,
fulfilled와 rejected가 출력될 것이다.

4. any

const promise1 = Promise.reject(0);

const promise2 = new Promise((resolve) 
			=> setTimeout(resolve, 100, 'quick'));

const promise3 = new Promise((resolve) 
			=> setTimeout(resolve, 500, 'slow'));

const promises = [promise1, promise2, promise3];

Promise.any(promises).then((value) => console.log(value));

any는 Promise 객체 중 가장 먼저 fulfilled 상태가 된 것의 상태와 결과가 반영된다.

위의 코드는 promise2가 가장 빨리 fulfilled가 되므로
그 결과값인 quick이 출력될 것이다.

만약 모두 rejected라면 AggregateError를 작업 실패 정보로 가지며 rejected가 된다.

논리 연산자 중 OR처럼, 어느 하나라도 fulfilled라면 되는 것이다.


📂 참고한 사이트

profile
[ ]-vation. 일상에 빗대 공감하고, 동기를 쥐어주는 개발자가 되고 싶습니다.

0개의 댓글