[javascript] Promise / async, await

parkheeddong·2023년 1월 21일

1. 프로미스

  • 상점에서 물건을 주문할 때 물건이 나올 때까지 시간이 걸린다고 생각해 보자. 소비자가 10초에 한번씩 물어보면, (다 됐나요->아니요->다 됐나요->아니요-> 다 됐나요->네) 비효율적이다. 따라서 상점에 주문한 후, 상점에서 작업이 완료되거나 실패하면 소비자에게 연락을 주는 것이 나을 것이다.

  • 이와 같이 사용되는 것이 '프로미스'이다.

  • 프로미스는 new Promise로 생성

let promise = new Promise(function(resolve, reject) {
  // executor (제작 코드, '가수')
});
  • new Promise에 전달되는 함수는 executor(실행자, 실행 함수)

2. resolve, reject

  • executor의 인수 resolve와 reject는 자바스크립트에서 자체 제공하는 콜백

  • 콜백함수란, 어떤 일이 완료되거나 실패했을 때 실행되는 함수

  • resolve는 성공한 경우, reject는 실패한 경우 호출

  • 즉, executor는 자동으로 실행되는데 여기서 원하는 일이 처리

  • 처리가 끝나면 executor는 처리 성공 여부에 따라 resolve나 reject를 호출합니다.


< 출처 : 코딩앙마-중급스크립트>

  • new Promise 생성자가 반환하는 promise 객체는 state, result를 프로퍼티로 받음
  • state — 처음엔 "pending"(보류)이었다 resolve가 호출되면 "fulfilled", reject가 호출되면 "rejected"로 변함
  • result — 처음엔 undefined 이었다
    resolve(value)가 호출되면 value로, reject(error)가 호출되면 error로 변함.

3. then, catch, finally

1) then

promise.then(
  function(result) { /* 결과(result)를 다룹니다 */ },
  function(error) { /* 에러(error)를 다룹니다 */ }
);
  • then의 첫 번째 인수는 프라미스가 이행되었을 때 실행되는 함수이고, 여기서 실행 결과를 받음

  • then의 두 번째 인수는 프라미스가 거부되었을 때 실행되는 함수이고, 여기서 에러를 받음

const pr = new Promise((resolve, reject) => {
  setTimeout(()=>{
    resolve('ok')
  }, 3000)
});
// 성공할 경우 state : pending -> fulfilled

pr.then(
  function(result) {
    console.log(result+'가지러가자');
  }, // 성공시 실행
  function(err) {
    console.log('다시 주문해주세요');
  }, // 실패 시 실행
);
                       

2) catch

  • reject인 경우에만 실행
  • 에러가 발생한 경우만 다루고 싶다면 then(null, errorHandlingFunction)같이 null을 첫 번째 인수로 전달하면 됨
  • catch는 then에 null을 전달하는 것과 동일하게 작동
                       
pr.then(
  function(result){}
).catch(
  function(err){}
)

3) finally

  • 이행이든 거부든 항상 실행
pr.then(
  function(result){}
).catch(
  function(err){}
).finally(
  function() {}
)
  • 프라미스가 처리되면(이행이나 거부) f가 항상 실행된다는 점에서 .finally(f) 호출은 .then(f, f)과 유사

  • 쓸모가 없어진 로딩 인디케이터(loading indicator)를 멈추는 경우같이, 결과가 어떻든 마무리가 필요하면 finally가 유용

const pr = new Promise((resolve, reject)=> {
  setTimeOut(()=>{
    resolve('ok');
  }, 10000);
});

console.log('시작');
pr.then((result)=> {
  console.log(result);
})
  .catch((err)=> {
  console.log(err);
})
  .finally(()=>{
  console.log('끝');
}); // 시작 => ok => 끝
         

4. 3개의 주문 받기

1) callback으로 구현

const f1 = (callback) => {
  setTimeout( function() {
    console.log('1번 주문 완료');
    callback();
  }, 1000);
};

const f2 = (callback) => {
  setTimeout( function() {
    console.log('2번 주문 완료');
    callback();
  }, 3000);
};

const f3 = (callback) => {
  setTimeout( function () {
    console.log('3번 주문 완료');
  }, 2000);
};

console.log('시작');
f1( function() {
  f2( function () {
    f3 ( function() {
      console.log('끝');
    });
  });
});

//callback chaining

2) promise로 구현

  • promise chaining
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() => {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = () => {
  console.log(message);
  return new Promise((res, rej)=>{
    setTimeout(()=>{
      res('2번 주문 완료');
    }, 3000);
  });
};


const f3 = () => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(()=>{
      res('3번 주문 완료');
    }, 2000);
  });
};
console.log('시작');

f1()
  .then((res) => f2(res))
  .then((res) => f3(res))
  .then((res) => console.log(res))
  .catch(console.log)
  .finally(()=>{
  console.log('끝');
})

5. promise.all


Promise.all([f1(), f2(), f3()]).then(res=>{
  console.log(res);
}) // ["1번 주문 완료","2번 주문 완료","3번 주문 완료"]

6. promise.race

Promise.race([f1(), f2(), f3()]).then(res=>{
  console.log(res);
}) 

6. async, await

async function getName() {
  return 'Mike';
}

console.log(getName()) // object Promise


getName().then((name)=> {
  console.log(name); // Mike
})


async function getName2() {
  return Promise.resolve('Tom');
}

getName2().then((name) => {
  console.log(name); // Tom
})


// await : async 내부에서 사용가능


async function showName3() {
  const result = await getName('Mike');
  console.log(result);
}

console.log('시작');
showName3();

0개의 댓글