TIL(20.04.27)자바스크립트 비동기 (Promise, async, await)

이민택·2020년 4월 27일
0

TIL

목록 보기
39/44

자바스크립트 비동기 처리

비동기적인 처리란 어떤 하나의 처리를 하는 과정중에 다른 처리도 동시에 진행할 수 있는 것을 의미한다. 그림으로 예시를 들면 아래와 같다

위와 같이 비동기적으로 처리를 하게 되면 각각의 작업이 독립적으로 실행되기 때문에 다른 하나의 작업이 막혀서 다른 작업을 못하는 동기 적인 문제가 사라진다. 그러나 아래와 같은 문제가 생긴다

비동기적인 작업을 동기적으로 수행하고 싶을 때

제목과 같이 어느정도 순서를 가지고 비동기적인 작업을 수행해야 할 때 비동기적으로 callback을 이용해서 작성하게 되면 아래와같은 콜백안에서 콜백을 부르고 이러한 과정이 반복되게 된다.

위와 같이 프로그램을 작성하게 되면 가독성이 떨어져서 유지보수가 힘들어진다 이런한 문제를 해결해 주는 것이 promise이다

Promise

promise는 비동기 연산이 종료된 이후의 결과값이나 실패 이유를 처리하기 위한 처리기( then ) 를 연결할 수 있도록 해준다 promise를 이용하면 비동기적 메소드를 동기적 메소드 처럼 사용이 가능하다.

Promise 의 상태

대기(pending)

이행되거나 거부되지 않은 초기 상태이다 new Promise를 이용하여 프로미스를 생성하면 적용되는 상태이다

이행(fulfilled)

프로미스의 연산이 성공적으로 완료되었을 때를 의미한다

거부(rejected)

프로미스의 연산이 실패했을 경우

프로미스의 이행,거부의 상태를 then, catch메서드가 받아서 처리가 가능하다 then은 보통 이행상태의 프로미스의 결과를 catch는 거부상태의 프로미스의 결과를 받는다. then과 catch는 프로미스를 다시 반환하기 때문에 연결이 가능하다.

  • resolve 메서드 : 주어진 값으로 이행하는 프로미스 객체를 반환한다 반환된 프로미스는 이전 then의 마지막 리턴 값을 받고 그렇지 않은 경우 주어진 값으로 실행한다.
  • reject 메서드 : 주어진 이유로 거부하느 프로미스 객체를 반환한다
let myFirstPromise = new Promise((resolve, reject) => {  
  setTimeout(function(){
    resolve("Success!");
  }, 250);
});

myFirstPromise.then((successMessage) => {
  console.log("Yay! " + successMessage);
});

async, await

async 키워드는 함수앞에 붙여서 사용이 가능하다 async가 붙은 함수는 암시적으로 promise를 사용하여 결과를 반환한다. await키워드는 비동기 함수를 async 함수 안에서 실행 할 때 앞에 붙여 사용할 수 있다 await가 붙은 채로 실행된 비동기 함수는 동기적인 함수처럼 비동기 함수의 실행이 끝날 때 까지 기다렸다가 코드가 실행된다.

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);
  console.log('end');
  
}
//calling 
//resolved
//end 출력된다.

asyncCall();

await 와 promise then의 차이

병렬적으로 프로미스를 실행하면 await의 경우 순서에 맞게 실행하지만 promise의 then은 동시에 실행한다

var resolveAfter2Seconds = function() {
  console.log("starting slow promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(20);
      console.log("slow promise is done");
    }, 2000);
  });
};

var resolveAfter1Second = function() {
  console.log("starting fast promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(10);
      console.log("fast promise is done");
    }, 1000);
  });
};

var sequentialStart = async function() {
  console.log('==SEQUENTIAL START==');

  const slow = await resolveAfter2Seconds();
  console.log(slow);

  const fast = await resolveAfter1Second();
  console.log(fast);
}

var parallel = function() {
  console.log('==PARALLEL with Promise.then==');
  resolveAfter2Seconds().then((message)=>console.log(message));
  resolveAfter1Second().then((message)=>console.log(message));
}

sequentialStart(); // 3초가 걸린다
setTimeout(parallel, 3000);  //2초가 걸린다

위와 같은 결과가 나온다 그러나 await의 경우도 아래와 같이 사용하면 2초가 걸리게 된다.

var concurrentStart = async function() {
  console.log('==CONCURRENT START with await==');
  const slow = resolveAfter2Seconds(); // starts timer immediately
  const fast = resolveAfter1Second();

  console.log(await slow);
  console.log(await fast); // waits for slow to finish, even though fast is already done!
}

참조 문서
mdn promise
mdn async

profile
데이터에 소외된 계층을 위해 일을 하는 개발자를 꿈꾸는 학생입니다

0개의 댓글