기록

Promise, async/await 본문

Node.js/Node.js 교과서

Promise, async/await

mnmhbbb 2021. 2. 19. 02:47

https://youtu.be/NEaDPHNflGI

1. 프로미스

: 내용이 실행은 되었지만, 결과를 아직 반환하지 않은 객체.
: 자바스크립트 비동기 처리를 위한 객체

실행 자체는 동기로 함.
원할 때(=then을 붙였을 때) 결과를 반환함.
즉, 코드를 분리할 수 있다!(콜백함수와의 차이점)

기본적으로 프로미스를 new Promise로 생성하는데,
그 내부에 resolve와 reject를 매개변수로 갖는 콜백함수를 넣음. 이 부분은 동기로 실행됨!
new Promise() 이 부분은 동기로 실행됨!
물론 실행은 됐으나, 결과값은 then이나 catch 메서드를 통해 받음.
이 부분은 프로미스가 가지고 있는 값임. 
(프로미스는 내부까지는 동기임. 그러나 then을 만나는 순간 비동기로 감.)

const condition = true; //true면 resolve, false면 reject

const promise = new Promise((resolve, reject) => {
  if (condition) {
    resolve('성공');
  } else {
    reject('실패');
  }
};

 

일단 프로미스가 들고 있다가 나중에 원할 때 꺼낼 수 있음.
바로 아래처럼.

promise
  .then((message) => {
    console.log(message);
  })
  .catch((error) => {
   console.log(error);
 })
  .finally(() => {
   console.log('무조건');
 });

실행이 완료되지 않았으면 완료된 후에 then 내부 함수가 실행됨
성공하면 resolve()를 호출 -> then으로 연결
실패하면 reject()를 호출 -> catch로 연결
finally 부분은 무조건 실행됨

콜백과 가장 큰 차이점은,
콜백은 일단 무조건 그 콜백함수를 가지고 있어야 함.
다음 예시처럼, setTimeout 안에 callback을 무조건 들고 있어야 함.

function callback() {};

setTimeout(callback, 3000);

일반적으로 자바스크립트의 비동기 처리 코드는 콜백을 사용해야지 코드의 실행 순서를 보장받을 수 있음.

 

프로미스는 이와 달리 코드를 분리할 수 있다는 큰 특징.
일단 실행해놓고, 다른 동작을 실컷하다가 필요할 때 then을 붙여서 가져올 수 있음.

const promise = setTimeoutPromise(3000);

console.log('딴짓');
console.log('딴짓');
console.log('딴짓');
console.log('딴짓');
console.log('딴짓');

promise.then(() => {
  console.log('지금 할래!');
});

그래서 코드가 깔끔해짐

또한, 그 유명한 콜백지옥! 중첩되는 문제를 깔끔하게 해결함.

Promise.all 은 여러 프로미스를 동시에 실행하는데, 하나라도 실패하면 catch로 감.
요즘은 all 보다 allSettled를 많이 쓴다고 함.


2. async/await

에이싱크 어웨이트도 프로미스인데, 프로미스를 한 번 더 깔끔하게 줄임

.then
.then
.then 이것들을 더 줄여보자이거지.

async function 함수명() {
  await 비동기_처리_메서드_명();
}

await이 then 역할을 함. 
"먼저 함수의 앞에 async 라는 예약어를 붙입니다. 그러고 나서 함수의 내부 로직 중 HTTP 통신을 하는 비동기 처리 코드 앞에 await를 붙입니다. 여기서 주의하셔야 할 점은 비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await가 의도한 대로 동작합니다. 일반적으로 await의 대상이 되는 비동기 처리 코드는 Axios 등 프로미스를 반환하는 API 호출 함수입니다.(캡틴판교님)"

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

기존에는
프로미스 Users.findOne() 을 실행하고
.then(결과값user) 이런 방식이라면,

 

//after
async function findAndSaveUser(User) {
  let user = await Users.findOne({});
  user.name = 'zero';
  user = await user.save();
  user = await Users.findOne({ gender: 'm' });
  //생략
}

aync, await은 오른쪽에서부터 실행된다는 느낌으로,,
Users.findOne이라는 프로미스가 성공해서 then(=await) 되면 결과값이 user에 저장.

변수 = await 프로미스; 인 경우 프로미스가 resolve된 값이 변수에 저장됨
변수 = await 값; 인 경우 그 값이 변수에 저장됨

추가 예시(캡틴판교)

function fetchItems() {
  return new Promise(function(resolve, reject) {
    var items = [1,2,3];
    resolve(items)
  });
}

async function logItems() {
  var resultItems = await fetchItems();
  console.log(resultItems); // [1,2,3]
}

 

 

async 함수 안에 return 값이 있다면?

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

1) main().then((name) => ... );
2) const name = await main()

async/await도 프로미스이기 때문에 프로미스 문법을 따름.
그래서 then으로 가져올 수도 있고, 아니면 배운대로 await으로.

 

단, async/await은 reject를 처리할 부분이 없어서 try, catch로 감싸줘야 함

async function main() {
  try {
    const result = await promise;
  
  } catch (error) {
    console.log(error);
  }
}

 

또한, 화살표함수도 async/await이 가능함

const findAndSaveUser = async (Users) => {
  try {
    let user = await Users.findOne({});
    
    //생략
  } catch (error) {
    console.error(error);
  }
};

 

for await ( 변수 of 프로미스배열) 

const promise1 = Promise.resolve('성공1');
const promise2 = Promise.resolve('성공2');

(aync () => {
  for await (promise of [promise1, promise2]) {
    console.log(promise);
  }
})();

반복문을 돌리면서 then(=await)을 붙일 수 있음

 

+) 실무에서 prototype에 대한 이해가 많이 중요한가요?

제로초님의 경우는 함수 위주로 하기 때문에 거의 안쓰지만,
클래스로 만들 수 있는 것도 다 함수로 하고 그럼.
클래스기반으로 객체지향프로그래밍 하는 사람들은 많이 씀.

다른 사람의 라이브러리를 분석하거나 할 때 함수형일 수도, 객체지향일 수도 있으니까
코드를 이해하려면 모두 알고 있어야 함..
코드를 자유자재로 짤 수 있으면 거기서 한 단계 더 나아가기 위해서는 다른 사람의 코드도 읽을 줄 알아야 함.

Comments