[데브코스] 프론트엔드 엔지니어링 TIL(13일차)

홍건우·2023년 6월 22일
0

데브코스

목록 보기
10/17
post-thumbnail

Promise

  • 비동기 작업을 제어하기 위해 나온 개념
  • callback hell에서 어느정도 벗어날 수 있게 도와줌
  • Promise로 정의된 작업끼리는 연결이 가능하며 이를 사용해 코드의 depth가 크게 증가히지 않는 효과가 있음

기본 사용 방법

const promise = new Promise((resolve, reject) => {
  // promise 내부에서 비동기 상황이 종료될 때, resolve 함수 호출
  // promise 내부에서 오류 상황일 때, reject 함수 호출
})

function asyncPromiseWork() {
  // ...
  return new Promise((resolve, reject) => {
    // promise 내부에서 비동기 상황이 종료될 때, resolve 함수 호출
    // promise 내부에서 오류 상황일 때, reject 함수 호출
    // ...
    return resolve('completed');
  })
}

// Promise는 then을 이용해 비동기 작업 이후 실행할 작업을 지정함
// then의 result에는 resolve를 호출하며 넘긴 completed가 들어있음
asyncPromiseWork().then(result => console.log(result));

promise chaining

  • 순차적으로 처리해야하는 비동기 작업이 여러 개 있을 경우 사용
  • promise.then의 결과 값으로 promise가 반환되기 때문에 .then을 체인 형식으로 사용이 가능
new Promise((resolve, reject) => setTimeout(() => resolve(1), 100))
  .then(result => {
    console.log(result); // 1
    return result + 1;
  }).then(result => {
    console.log(result); // 2
    return result + 2;
  }).then(result => {
    console.log(result); // 4
  })
/*
 .then의 return 값으로 promise를 반환하는 경우 이어지는 .then은 반환된 promise가
	처리될 때 까지 기다렸다가 결과 값을 받는다.
*/
new Promise((resolve, reject) => setTimeout(() => resolve(1), 100))
  .then(result => {
    console.log(result); // 1
    return new Promise((resolve, reject) =>
			setTimeout(() => resolve(result + 1), 100)
		);
  }).then(result => {
    console.log(result); // 2
    return result + 2;
  }).then(result => {
    console.log(result); // 4
  })

promise chaining 오류 처리

// Promise의 then내에서 promise를 return하는 경우 또 다른 then으로 연결 가능
fisrtPromiseWork()
  .then(result => {
    return secondPromiseWork(result);
  }).then(result => {
    return thirdPromiseWork(result);
  }).then(result => {
    return finalPromiseWork(result);
  }).catch(e => { // promise chain중 작업이 실패했을 경우 catch로 잡기 가능
    console.log('오류 발생');
  }).finally(() => { // 작업의 성공 여부와 상관 없이 마지막으로 실행
    console.log('작업 끝');
  })
  • catch를 넣지 않은 경우 promise chain 중 에러가 발생했을 때 chain이 멈춤 ⇒ catch를 사용하자!
  • catch를 중간에 넣고 작업을 연결해도 동작함

callback함수를 promise 형태로 만들기

const delay = (delayTime) => new Promise((resolve) => {
  setTimeout(resolve, delayTime);
})

delay(5000)
  .then(() => {
    return delay(3000);
  }).then(() => {
    console.log('complete');
  })

promise 내장 함수

Promise.all(iterable)

  • iterable에 주어진 모든 promise가 동시에 실행된 후 새로운 promise를 반환
  • 여러 promise를 동시에 처리할 때 유용함
  • 주어진 promise 중 하나라도 reject되는 경우 첫 번째로 reject된 promise를 이유로 자신도 거부함
Promise.all([
  new Promise(resolve => setTimeout(resolve, 3000, 1)), // 1
  new Promise(resolve => setTimeout(resolve, 2000, 2)), // 2
  new Promise(resolve => setTimeout(resolve, 1000, 3))  // 3
]).then(result => console.log(result)); // 프라미스 전체가 처리되면 1, 2, 3이 반환

Promise.race(iterable)

  • Promise.all과 비슷하지만 가장 먼저 처리되는 프로미스의 결과(성공, 실패)를 반환
  • 많이 사용하진 않음
Promise.race([
  new Promise(resolve => setTimeout(resolve, 3000, 1)), // 1
  new Promise(resolve => setTimeout(resolve, 2000, 2)), // 2
  new Promise(resolve => setTimeout(resolve, 1000, 3))  // 3
]).then(result => console.log(result)); // 3 반환

Promise.any(iterable)

  • Promise.all과 비슷하지만 가장 먼저 성공(resolve)한 promsie가 존재하면 종료
Promise.any([
  new Promise(resolve => setTimeout(resolve, 3000, 1)), // 1
  new Promise(resolve => setTimeout(resolve, 2000, 2)), // 2
  new Promise(resolve => setTimeout(resolve, 1000, 3))  // 3
]).then(result => console.log(result)); // 3 반환

Promise.allSettled()

  • 주어진 모든 프로미스를 수행한 후 각 프로미스에 대한 결과를 나타내는 객체 배열을 반환
  • 각 promise의 실행 결과를 알고 싶을 때 사용
Promise.allSettled([
  new Promise(resolve => setTimeout(resolve, 3000, 1)), // 1
  new Promise(resolve => setTimeout(resolve, 2000, 2)), // 2
  new Promise(resolve => setTimeout(resolve, 1000, 3))  // 3
]).then(result => console.log(result));
// [
//   { status: 'fulfilled', value: 1 }, 
//   { status: 'fulfilled', value: 2 },
//   { status: 'fulfilled', value: 3 }
// ]
// reject된 경우 status 값이 rejected로 반환됨

Promise.resolve

  • 주어진 값으로 이행하는 Promise.then 객체를 만듬
  • 주어진 값이 promise인 경우 promise가 반환됨
  • return type을 promise로 맞춰줄 때 종종 사용함
const promise1 = Promise.resolve(123);

promise1.then((value) => {
  console.log(value); // 123
});

async, await

  • Promise가 callback depth를 1단계로 줄여주지만 아직 불편한 점이 있음
    • .then() 체이닝을 통해 비동기 작업을 하므로 코드가 복잡함
    • .catch()를 통해 오류를 처리하므로 오류 처리 로직이 분리되어 가독성이 떨어짐
      ⇒ async, await는 try, catch, finally를 사용!
  • async, await를 사용하면 Promise를 비동기 작업이 수행되지만 동기 코드처럼 보이게 코드 작성이 가능
const delay = (delayTime) => new Promise((resolve) => {
  setTimeout(resolve, delayTime);
})

// Promise를 사용
const work = () => {
  delay(100)
    .then(() => {
      console.log('work 1 complete');
      return delay(100);
    }).then(() => {
      console.log('work 2 complete');
      return delay(100);
    }).then(() => {
      console.log('work 3 complete');
      return delay(100);
    }).then(() => {
      console.log('all complete');
    })
}

work();

// async, await를 사용 => 코드 가독성이 좋음!
const work2 = async () => {
  await delay(100);
  console.log('work 1 complete');
  await delay(100);
  console.log('work 2 complete');
  await delay(100);
  console.log('work 3 complete');
  await delay(100);
  console.log('all complete');
}
work2();

async 함수 정의 방법

  • async 키워드가 붙은 함수는 실행 결과를 Promise로 감싸게됨
async function asyncFunc () {
  const res = await request(...);
}

const asyncFunc = async () {
  const res = await request(...);
}

fetch api

  • 비동기 https 요청을 좀 더 편하게 사용할 수 있는 API
  • XMLHTTPRequest를 대체
  • Promise 기반으로 동작 ⇒ promise chaining 응용 가능!
  • fetch의 기본 응답 결과는 Response 객체!
    • Response 객체를 얻은 뒤엔 응답을 json으로 바꾸거나 text로 바꾸는 등의 처리를 해줘야함
  • fetch는 HTTP error가 발생해도 reject되지 않음(네트워크 에러나 요청이 완료되지 않은 경우만 reject 됨) ⇒ fetch가 성공했는지 확인하는 과정이 필요함(response의 status code나 ok를 확인)

사용 방법

fetch('https://dummyjson.com/products/1')
  .then(res => res.json())
  .then(json => console.log(json))
// 오류 처리
fetch('https://dummyjson.com/products/undefined') // 존재하지 않는 url
  .then(res => {
    if (res.ok){
      return res.json();
    }
    throw new Error('요청 중 오류 발생');
  })
  .then(json => console.log(json))
  .catch(e => console.log(e.message));
profile
컴퓨터공학과 학생입니다

0개의 댓글