반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

Promise, async/await 본문

JS/인간 JS엔진

Promise, async/await

5_hyun 2024. 1. 25. 00:49

Promise

프로미스는 내용이 실행은 되었지만 결과를 아직 반환하지 않은 객체

=> 나중에 사용 가능

const condition = true;
const promise = new Promise(()=> {
    // 이 if 문은 동기로 실행
    if (condition){
      resolve('성공');
     } else {
       reject('실패');
      }
 });

promise
  .then((message) => {
     console.log(message);
   })
  .catch((error) => {
    console.error(error);
  });

 

  • new Promise() 안의 if 문은 동기로 실행
  • 성공하든 실패하든 값을 promise에서 값을 가지고 있음
  • then, catch에서 값을 원할 때 꺼낼 수 있다.
  • callback과 다른 점으로는 코드를 분리할 수 있냐 없냐가 엄청난 차이 
  • 콜백 지옥도 막을 수 있음

비동기 callback과 promise 비교

(참고로 callback은 동기, 비동기 다 있음)

-비동기 callback

function callback() {}
setTimeout(callback, 3000)
  • 가장 아쉬운 점이 callback 부분이 강제인 점
  • 3초 뒤라는 조건이 달성되면 바로 실행 됨

-promise

const promise = new Promise(resolce, reject) => {
  setTimeout(() => {
    resolve)
  }, 3000);
 });

// 다른 코드 실행
// 다른 코드 실행
// 다른 코드 실행

promise.then(() => {
  //지금 실행
});
  • promise에 값을 담아 놓을 수 있음
  • 다른 동작을 실행하다가 내가 원할 때 사용가능

콜백 지옥과 promise 지옥

-콜백 지옥

step1(function (value1) {
    step2(function (value2) {
        step3(function (value3) {
            step4(function (value4) {
                step5(function (value5) {
                    step6(function (value6) {
                        // Do something with value6
                    });
                });
            });
        });
    });
});
  • callback를 사용하면 위 코드처럼 콜백 지옥이 발생
  • 콜백 지옥의 가장 근본적인 문제점은 결괏값을 바로 받아야 한다는 점

 

-promise 지옥

step1
  .then(() => {
    //처리
    })
  .then(() => {
    //처리
    })
  .then(() => {
    //처리
    })
  .catch(() => {
    //처리
    })
  • 콜백 지옥은 해결이 됨
  • 하지만 then, catch 지옥이 생기게 됨

여러 Promise 해결법

-Promise.all

// promise 지옥
const promise1 = Promise.resolve('성공1');
const promise3 = Promise.resolve('성공2');

// 해결책1
Promise.all([promise1, promise2])
  .then((result) => {
    console.log(result); // ['성공1', '성공2']
  })
  .catch((error) => {
    console.error(error);
  });
  • Promise.all을 사용하면 해결이 가능
  • 하지만 하나라도 실패하면 다 catch로 감 => 성공한 결괏값들 다 날라감
  • catch
    • catch는 "Promise.all([promise1, promise2])"에 대한 catch가 아니다!
    • "Promise.all([promise1, promise2]).then((result) =>...)"에 대한 catch이다.
      • then에서 에러나는 것도 catch로 간다.

-Promise.allSettled

// 해결책1
Promise.allSettled([promise1, promise2])
  .then((result) => {
    console.log(result); // ['성공1', '성공2']
    // 실패한 것만 필터링해서 다시 시도 가능
  })
  .catch((error) => {
    console.error(error);
  });
  • 성공한 것과 실패한 것을 구분해 줌
  • 즉, 실패한 것만 필터링해서 다시 시도 가능

async/await(Promise 지옥 해결)

async/await

-Promise 지옥인 코드

function findAndSaveUser(Users) {
  Users.findOne({})
    .then((user) => {
      user.name = 'zero';
      return user.save();
    })
    .then((user) => {
      return Users.findOne({ gender: 'm' });
    })
    .then((user) => {
      // 생략
    })
    .catch(err => {
      console.error(err);
    });
}

 

-async/await 코드

async function findAndSaveUser(Users) {
  let user = await Users.findOne({});
  user.name = 'zero';
  user = await user.save();
  user = await Users.findOne({ gender: 'm' });
  // 생략
}
  • then을 await으로 대체
  • 결괏값들을 미리 받는 것
    • let user = await Users.findOne({}); 그렇기에 이 부분은 "왼쪽 <- 오른쪽"으로 실행
    • 결국 await이 나오면 "왼쪽 <- 오른쪽"으로 실행이라 생각하면 됨
  • await을 사용하려면 async는 필수였지만, 요즘은 await만 써도 됨

-Top-Level await

// promise 코드
const promise = new Promise(...);
promise.then((result) => ...);

// await 코드
const result = await promise;

Top-Level await이란 방식이 나와서 이렇게 사용 가능

aysnc에서 return 한 값 받기

async funxtion main() {
  const result = await promise;
  return 'zerocho';
}

//then으로 받기
const name1 = main().then((name) => ...);

// await으로 받기
const name2 = await main();
  • async에서 return한 값은 then 혹은 await으로 받아야 함
  • async도 promise라서 이렇게 해야 한다.

에러 처리

async funxtion main() {
  try {
    const result = await promise;
    return 'zerocho';
  } catch (error) {
    // 에러 처리
  }
}

//then으로 받기
const name1 = main().then((name) => ...);

// await으로 받기
const name2 = await main();
  • try/catch를 활용하여 에러 처리 필요

for await of

const promise1 = Promise.resolve('성공1');
const promise2 = Promise.resolve('성공2');
(async () => {
  for await (promise of [promise1, promise2]) {
    console.log(promise);
  }
})();
  • 앞에서 설명했듯이 await은 then임
  • for 문을 통해 반복문을 돌리면 promise에 다 then이 붙어서 나옴
  • 따라서 for await of는 promise들을 반복할 때 자주 쓰임

요약

  • 항상 async/await을 사용하는게 좋은건 아니다
  • 여러 promise들이 있을 땐, Promise.allSettled이 더 효율적

 

-출처

https://www.youtube.com/watch?v=NEaDPHNflGI&list=PLcqDmjxt30Rt9wmSlw1u6sBYr-aZmpNB3&index=10

https://www.youtube.com/watch?v=0f-jNhnN0Qc&list=PLcqDmjxt30Rt9wmSlw1u6sBYr-aZmpNB3&index=11

 

728x90
반응형

'JS > 인간 JS엔진' 카테고리의 다른 글

Promise에도 동기는 있다!  (0) 2024.01.27
비동기는 동시가 아니다  (1) 2024.01.27
블록 스코프와 매개변수  (0) 2024.01.24
this를 분석할 수 없는 케이스  (0) 2024.01.23
this(this는 호출 시 결정)  (1) 2024.01.23
Comments