🎯Asynchronous & Promise 비동기적 사고!🎱

2020. 9. 21. 21:55기초 Java Script

출처: https://adrianmejia.com/asynchronous-vs-synchronous-handling-concurrency-in-javascript/

Asynchronous? 비동기 ?

동기적으로 프로그램을 실행하게 된다면, 업무는 순차적으로 실행되어 시간이 오래 걸리게 됩니다. (위 그림의 오른쪽과 같이!)  하지만 비동기적으로 프로그램을 실행하게 된다면 오래 걸리는 작업이 진행되는 동안 CPU에 다른 일을 시킬 수 있습니다. 그러면 동일한 작업을 할 때, 동기적인 실행은 시간이 아주 오래 걸리지만 비동기적인 실행은 그 중에 가장 오래걸리는 업무를 끝내는 시간이 전체 업무를 실행하는데 소요하는 시간과 같아질 것입니다. 


흠~ 그럼 비동기적으로 실행을 어떻게 정리해서 할 수 있을까요? 

callBack

const Paprika = (string, callback) => {
    setTimeout(
      () => {
        console.log(string)
        callback()
      }, 
      3000)
  }
 
  const tasteAll = () => {
    Paprika("tangy", () => {
      Paprika("spicy", () => {
        Paprika("what the fxxk", () => {})
      })
    })
  }

  tasteAll() 

콜백함수를 통해서 표현할 수 있습니다. 위처럼 데이터와 콜백함수를 받는 form을 반복한다면 3초마다  "tangy","spicy", "what the fxxk"이 출력되는 것을 확인할 수 있습니다.  하지만 이렇게 콜백만 이용할 경우 코드가 길어질수록 오른쪽으로 쏠리는 현상이 일어나면서 'callback hell'을 만들 수 있습니다. 그래서 promise를 사용하는 것을 권장합니다. 

Promise

const Paprika = (string) => {
   let taste = string + '!';
  return new Promise((resolve,reject) => {
    setTimeout(
      () => {
        console.log(string)
        resolve(taste)
      }, 
      3000)
    
  })
  }
 
  const tasteAll = () => {
   Paprika('OMG spicy')
   .then((data)=> {
   return Paprika(data)
   })
   .then((data)=> {
   return Paprika(data)
   })
   }

  tasteAll() 

 promise 라는 constructor이름으로 리턴을 하는 형태로 resolve에는 실행하는 값에 에러가 없었을 때 담겨니는 값, reject은 실행하는 값에 에러가 생겼을 경우 담아줍니다. 이는 .then 과 .catch를 통해서 이후 처리를 할 수 있습니다!  이를 통해서 보다 직관적으로 비동기적인 실행을 순차적으로 할 수 있습니다. 

.then에서 리턴한 값이 다음 then으로 이동하니 체이닝을 할 때는 이 구조를 확인해야한다. 그리고 promise.all 중에서 하나라도 실패한다면 .catch로 가게 되니 명심해주세요! promise를 사용하게 된다면 blocking이 아닌 non blocking으로 여러가지 일을 할 수 있습니다. (# blocking은 화면이 멈추면서 아무 것도 못 하는 상황이라 생각하면 좋습니다.)

하지만 이렇게 만든 promise는 또 다른 promise로 리턴하기 때문에 일반적인 함수 환경에서 사용하기 위해서는 동기적인 형태로 바꿔줘야합니다.

async / await

const Paprika = (string) => {
   let taste = string + '!';
  return new Promise((resolve,reject) => {
    setTimeout(
      () => {
        console.log(string)
        resolve(taste)
      }, 
      3000)
    
  })
  }
 
 const tasteAll = async function(){
   return await Paprika('OMG spicy');
 }

  tasteAll(); 

function 앞에 async를 붙이고 사용하려는 promise 앞에 await를 쓴다면 동기적으로 사용할 수 있습니다. 이때 프로미스를 변수에 담아서 여러 다른 함수에 자유롭게 사용할 수 있습니다. 

Promise의 상태


3가지 상태 pending  - 수립이나 에러가 나타나기 전  fulfill - 비동기 요청이 성공적으로 완료가 되었을 때     rejected - 비동기 요청중 에러발생  # fulfilled 와 rejected를 합쳐서 settled라고 한다. 

 

  

await는 프로미스로 리턴되는 함수들만 사용 가능합니다.