자바스크립트의 비동기 처리 방법(Async/Await ,Generator)

Dohyeon Kong·2024년 3월 29일
0

JavaScript🟡

목록 보기
11/13
post-thumbnail

Async / Await

  • async, await는 ES8에서 도입된 비동기 작업을 처리하기 위한 패턴을 의미한다.
  • Callback과 Promise보다 간결히 사용할 수 있다.
  • 가독성이 매우 올라가며 반환값은 resolve 객체 혹은 reject 객체이다.
  • throw 키워드를 사용해서 reject를 반환해준다.
// async와 await 기본 형식 코드
const asyncFunction = async() => {...}

const value1 = await asyncFunction();
const value2 = await asyncFunction();
const value3 = await asyncFunction();                           
// async와 await 기본 형식 코드
// async는 Promise 상자를 반환
// await는 Promise 상자를 연다

//Promise
const greetPromise = () => {
  return new Promise((resolve, reject) => {
  	resolve('hello')
  })
}

// Async 형태, 기본적으로 Promise를 리턴한다.
const greetAsync = async() => {
 return 'hello' 
}

Async/Await 예외 처리 방식

  • try - catch문법을 사용한다.
const greet = async () => {
  const isSuccess = true;
  if(isSuccess){
    return 'Hello'
  }
  else{
    throw 'Bye'
  }
}
try{
  const greetText = await greet();
  console.log(greetText); // hello
}catch(e){
  console.log(e); // Bye
}

Generator()

제너레이터란 중간에 원하는 부분에서 멈추었다가 그부분부터 다시 실행할 수 있는 능력을 가진 함수를 의미한다.

Generator 함수 사용 방식

  • Generator 함수는 function* 키워드를 사용하며 아래 코드와 같다.
//Generator 함수 기본 코드
function* generatorFunc1(){ ... }
const generatorFunc2 = function* () {...}
  • 제너레이터 함수는 화살표 함수를 사용하지 않는다.
  • 별표 * 는 function 키워드와 함수 이름 사이면 아무데나 붙여도 되지만, 일관성의 목적으로 function키워드 바로 뒤에 붙이는 것을 권장한다.

Generator 함수와 일반 함수의 차이점은 무엇인가?🤔

1. Generator 함수는 함수 호출자에게 자기 자신의 실행의 제어권을 양도(yield)할 수 있다.

  • 일반 함수는 함수가 어딘가에서 호출되면 그 함수에 대한 제어권은 호출된 함수 본인에게 넘어간다.

  • 예를들어 친구 B가 친구 A에게 소개팅을 해준다고 가정해보자. 친구 B는 함수 호출자가 되고 친구 A는 일반함수가 된다. 함수 B는 소개팅을 주선해주었지만 소개팅에 어떻게 임할지는 친구A에게 달려있다.

  • 제너레이터는 함수 실행의 제어궈을 함수 호출자에게 양도할 수 있다. 즉 함수 호출자는 함수 실행을 일시 중지시키거나 다시 시작하게 할 수 있다.

  • 예를 들어 친구 B가 친구 A에 소개팅에 개입해서 아바타 소개팅과 같이 되는 것을 의미한다.

2. Generator 함수는 함수 호출자와 함수의 상태를 주고받을 수 있다.

  • 일반 함수는 호출되는 순간 매개변수를 통해 함수 외부로부터 값을 전달받고 실행이 된다. 다시 말해 함수가 실행되고 있는 동안에는 함수 외부에서 함수 내부로 값을 전달하여 함수의 상태를 변경할 수 없다는 의미이다.

  • 제너레이터 함수는 함수 호출자와 양방향으로 함수의 상태를 주고받을 수 있다. 다시 말해 제너레이터 함수는 함수 호출자에게 자신의 상태를 전달할 수 있고, 함수 호출자로부터 추가적으로 상태를 전달받을 수 있다는 의미이다.

3. Generator 함수는 호출 시 제너레이터 객체를 생성해 반환한다.

  • 일반 함수는 호출이 되면 함수의 코드 블록을 실행시킨다.
  • 하지만 제너레이터 함수는 실행시키는 것이 아닌 제너레이터 객체를 생성해서 반환한다.

제너레이터 객체

  • 제너레이터 함수를 호출하였을 때 리턴되는 객체를 의미한다.
  • 제너레이터 객체는 이터러블이면서 동시에 이터레이터가 된다.

이터러블(iterable)

  • 이터러블은 이터러블 프로토콜을 준수한 객체를 의미한다.
  • 이터러블 프로토콜을 준수한다라는 의미는 Symbol.iterator를 프로퍼티로 사용한 메서드를 직접구현하거나 프로토타입 체인을 통해 상속받은 객체를 의미한다. => 배열, 문자열, Map, Set 모두 이터러블이다.
  • 제너레이터 객체는 이터러블이기 때문에 for...of문을 사용할 수 있다.

이터레이터(iterator)

  • 이터러블에 Symbol.iterator 메서드를 호출하였을 때 반환되는 값을 의미한다.
const maArr = [1, 2, 3]
const iterator = maArr[Symbol.iterator]()
  • 이터레이터는 next라는 메서드를 가지고 있는데, 이를 이용해서 각 요소를 순회할 수 있다.
  • next 메서드는 iterator result object가 반환되며 이 객체는 value와 done이라는 property를 가지고 있다.
const myArr = [1, 2, 3]
const iterator = myArr[Symbol.iterator]()
const iteratorResultObject = iterator.next()
console.log(iteratorResultObject) // {value : 1, done : false}

제너레이터 객체의 next, return 그리고 throw 메서드

  • 제너레이터객체는 이터레이터이기 때문에 next메서드를 사용할 수 있고, 이터레이터에는 없는 return과 throw, 두 가지 메서드를 추가로 사용할 수 있다.
function* function1(){
 try{
   yield "씹는다"
   yield "못본척한다."
   yield "바쁜척한다"
   yield "괜히 친구랑 통화르 더 길게 한다"
   yield "답장을 보낸다"
  
 }catch(e){
   console.log(e)
 }
}

const generator = function1()
const first = generator.next(); // {value : "씹는다", done : false}
const second = generator.next() // {value : "답장을 보낸다", done : false}
  • generator.return(parameter)은 인자로 전달받은 parameter를 value의 값으로, true를 done으로 하는 이터레이터 리절트 객체를 리턴한다.
  • generator.throw(parameter)는 인자로 전달받은 에러를 발생시키면서 value값으로 undefined를, done 값으로 true를 갖는 이터레이터 리절트 객체를 리턴한다.

yield와 next

  • yield는 제너레이터 함수를 멈추거나 다시 시작하는데 사용하는 키워드를 의미한다.

  • next 메서드를 사용하면 yield키워드가 사용된 표현식까지 실행되고 함수가 일시 중단된다.

  • 이때 함수의 제어권이 함수 호출자에게 양되된다. 다시 말해 next ㅔㅁ서드가 반복 호출될 때마다 다음 yield 표현식까지 실행과 중지가 반복되는 것을 의미한다.

  • 제너레이터 함수 특징 중 함수 호출자와 제너레이터 함수가 상태를 보고 새로 전달할 수 있다고 하는 방법으로 next() 메서드를 사용하는 것이다.

  • next() 메서드는 제너레이터가 아닌 일반 이터레이터에서 호출될 때 parameter가 필요없지만 제너레이터에선 인자를 전달할 수 있다.

function* function2(){
 const first = yield - 1000
 const second = yield(first + 100)
 return first + second
}
const generator = function2();

//next() 3번 호출
let first = generator.next() // {value : -1000, done : false}
let second = generator.next(-50) // {value : 50, done :false}
let third = generator.next(200) // {value : 150, done : true}

profile
천천히, 꾸준히, 그리고 끝까지

0개의 댓글