[JavaScript] Async/Await 개념

정호·2023년 4월 20일
0

JavaScript

목록 보기
11/12
post-thumbnail
post-custom-banner

비동기 처리 방식

특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드들을 수행하는 것 자바스크립트는 싱글 스레드 프로그래밍 언어이기 때문에 비동기 처리가 필수적이다.

비동기 처리는 그 결과가 언제 반환될지 알수 없기 때문에 동기식으로 처리하는 기법들이 사용되어야 하는데, 대표적으로 setTimeout이 있고 callbackpromise가 있다.

async/await 를 사용하면 비동기 처리를 좀 더 간단히 구현할 수 있다.

Promise 문법

function foo() {
	return new Promise((resolve, reject) => {
	    resolve('hello'); 
        // or reject(new Error('error');
	});
}

foo().then((e) => console.log(e));

Async

async function foo2(){ // async을 지정해주면 Promise를 리턴하는 함수가 된다.
  return 'hello_2'; //리턴값은 Promise{<resolved>: "hello2"} 자동 resolve해준다는걸 알 수있다.
  // reject는 throw 에러를 보낸다.
}

foo2().then((e) => console.log(e));

함수에 async만 붙이면 자동 Promise객체로 인식되고 return값은 resolve()값과 똑같다.

리턴값은 Promise{<resolved>: "hello_2"}
문자열이 리턴되는것이 아님

다음과 동일한 함수

async function foo(){ // async을 지정해주면 Promise를 리턴하는 함수와 같다.
  
  //return 'hello2';
  return Promise.resolve('hello'); // 똑같다
}

async & await

  • function 키워드 앞에 async만 붙여준다.

  • 비동기로 처리되는 부분 앞에 await만 붙여준다.

async가 붙은 함수는 Promise를 반환하고, Promise가 아니면 Promise로 감싸 반환한다.

await 키워드를 만나면 Promise가 처리(settled)될 때까지 기다린다. --> 처리가 완료되어 resolve(값) 되면 값만 따로 추출해서 리턴

await는 promise.then보다 가독성 좋고 쓰기도 쉽다.

async function foo() {

  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("Resolved"), 1000)
  });

  let result = await promise; // then방식에서는, promise.then(()=>{})을 통해 비동기를 받아야하지만
                              // await 키워드로 직관적 으로 볼 수 있다.

  alert(result); // "완료!"
}

foo();

async/awaitPromise를 대체하지는 않는다.
비동기는 Promise객체로 처리하고
async/await는 비동기를 동기식으로 처리하는 기법이다.
기존에는 Promise에 직접 .then()을 통해 동기처리를 했지만,
await를 사용하면 바로 동기처리가 되기 떄문이다.

Promise 사용

function num1(){
  return new Promise( (resolve, reject) => {
    setTimeout(() => resolve("num1"), 100);
  })
}

function num2(){
  return new Promise( (resolve, reject) => {
    setTimeout(() => resolve("num2"), 100);
  })
}

function Number(){
  num1()
    .then((n1) => { // 리턴값 === resolve()니까 then 가능
      num2()
        .then((n2) => console.log(`${n1} and ${n2}`)); 
    }) // 콜백지옥 
}

Number() // 결과 : num1 and num2

프로미스로 비동기 함수를 만들고, 동기 처리를 async로 하면 된다.

delay()라는 프로미스 객체 비동기 함수를 만들고,
async함수 num1, num2 동기처리를 한다.


function delay(){
  return new Promise( (resolve, reject) => {
    setTimeout(() => resolve(), 1000);
  })
}

async function num1(){
  await delay();
  return "num1";
}

async function num2(){
  await delay();
  return "num2";
}

function Number(){
  num1()
    .then((n1) => { // 리턴값 === resolve()니까 then 가능
      num2()
        .then((n2) => console.log(`${n1} and ${n2}`)); 
    }) // 콜백지옥
    
}

Number(); // 결과 : num1 and num2

콜백지옥

위의 코드에서 async에서 리턴한 값(Promise.resolve(값))then으로 처리할 필요는 없다.
resolve의 값을 추출해 변수에 할당하면 외부함수에서 처리할 수 있다.

function delay(){
  return new Promise( (resolve, reject) => {
    setTimeout(() => resolve(), 1000);
  })
}

async function num1(){
  await delay();
  return "num1";
}

async function num2(){
  await delay();
  return "num2";
}

async function Number(){
  let a = await num1(); //리턴값이 resolve()의 값이니까 대입 가능
  let b = await num2();
  console.log(`${a} and ${b}`);
}

Number(); // 결과 : num1 and num2

다음과 같이 a``b사이의 딜레이를 없애고 병렬 처리할 수 있다.

async function Number(){
  let getnum1 = num1(); // async함수를 실행시킨다. 논블록킹으로 백단에서 실행되게 된다.
  let getnum2 = num2(); // 리턴으로 프로미스 객체로 감싸진 결과값을 받는다.

  let a = await getnum1; // 리턴으로 받은 프로미스객체를 done(data)를 await으로 빼서 변수에 넣음
  let b = await getnum2; 
  // 본래라면 1초+1초 를 기다려야 하는데, 위에서 1초기다리는 함수를 한번에 불러왔기 때문에, 대충 1.001초만 기다리면 동기식으로 처리된다.
  console.log(`${a} and ${b}`);
}

async / await 예외 처리

(Promise의 reject()를 async에서 구현)
try.. catch -> throw
리턴값이 Promise객체이니 잡는 방법도 Promise.catch()방법과 같다.

async function p2(){ 
  throw 'error';
  //throw new Error("error");
  //await Promise.reject(new Error("error"));
  //return Promise.reject(new Error("error"));
}

p2()
  .then((n) => console.log(n))
  .catch((n) => console.log(n));
function p(){
  return new Promise((resolve, reject) => {
    reject("Error!!");
  },1000)
}

(async function p2(){ 
  try{
    await p(); // Promise에서 reject가 될때까지 await한다.
  }catch(e){
    console.error(e);
  }
})();
profile
열심히 기록할 예정🙃
post-custom-banner

0개의 댓글