ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] Promise 와 async/await
    Javascript 2023. 3. 14. 20:53

    비동기 처리란?

     자바스크립트는 기본적으로 싱글 스레드 언어이기 때문에, 하나의 호출 스택(call stack)에서 처리하는 프로세스이다. 이런 상황에서 자바스크립트는 비동기 처리를 하기 위해서 큐(Queue)를 사용한다.

     하나의 호출 스택에서 동기적 처리가 끝나면 큐에서 대기중인 비동기 함수들을 처리한다.

    setTime, addEventListener 메서드, ajax라 불리던 XMLHttpRequest 객체, fetch API 등이 대표적으로 비동기적으로 실행된다.

    콜백 지옥

     비동기 작업은 비동기 처리가 끝난 이후에 다음 처리를 실행하기 위한 용도로 사용하는데, 이런 흐름을 위해서 지속적으로 콜백 함수를 실행한다면 결과적으로 ‘콜백 지옥’에 빠지게 된다.

    // setTimeout 비동기 작업을 하는 sleep이라는 함수
    
    function sleep(callbacak) {
    	setTimeout(() => callback(), 1000);
    }
    
    sleep(()=>{
    	console.log("A");
    	slee(()=> {
    		console.log("B");
    		sleep(()=>{
    			console.log("C");
    		})
    	})
    })

    Promise

    Promise를 사용하려면 먼저 Promise 객체를 생성하고, ‘executor’라는 함수를 인자로 받는다.

    인자로 받은 ‘executor’ 함수는 resolve와 reject라는 함수를 호출할 수 있다.

    • resolve: 함수 안의 처리가 성공적으로 끝났을 때 호출해야 하는 콜백 함수
    • reject: 함수 안의 처리가 실패했을 때 호출해야 하는 콜백 함수

    Promise를 처리하는 then과 catch 메서드

    • then: resolve 함수는 Promise를 종료시키다. resolve 함수에 인수로 넘긴 값은 then 메서드에 인수로 넘긴 함수에 전달되어 다음 처리를 위해 사용된다.
    • catch: reject 함수는 Promise를 종료시킨다. reject 함수에 인수로 넘긴 값은 catch 메서드에 인수로 넘긴 함수에 전달되어 다음 처리를 위해 사용된다.

    즉, resolve와 then는 같은편 / reject와 catch는 같은편

    function findNumber(number) {
      return new Promise((resolve, reject) => {
        if (number < 10) reject(`오류: ${number}은 최소값보다 작습니다.`);
        resolve(number)
      })
    }
    
    const promise1 = findNumber(3)
    promise1
      .then((number) => {
        console.log(100 * number)
      })
      .catch((error) => {
        console.log(error)
      })
    
    const promise2 = findNumber(100)
    promise2
      .then((number) => {
        console.log(100 * number)
      })
      .catch((error) => {
        console.log(error)
      })

     Promise는 세 가지 상태를 지닌다. 바로 대기(pending), 이행(fulfilled), 거부(rejected) 이며 이행 상태일 때 then, 거부 상태일 때 catch 로 등록한 동작들이 실행된다. 지금까지 “성공” 이라고 이야기한 것들은 사실 “이행 상태“와 연계된 것이고, “실패“는 “거부“와 동일한 상태이다.

     Promise 의 의의를 한마디로 이야기 하자면, Promise 는 비동기 작업을 생성/시작하는 부분(new Promise(...))과 작업 이후의 동작 지정 부분(then, catch)을 분리함으로써 보다 유연한 설계를 가능토록 한다.

     

    Promise - 비동기 처리 여러 개를 병렬로 실행하기

     Promise 객체의 all 메서드를 사용하면 비동기 처리 여러 개를 병렬로 실행한다.

    Promise.all(iterable)

      terable 인수는 Promise 객체가 요소로 들어 있는 반복가능한 객체이다. 예를 들어 Promise 객체가 요소로 들어 있는 배열을 넘기면 Promise.all 메서드는 그 안의 요소로 들어 있는 모든 Promise 객체를 병렬로 실행한다.

    Async - 비동기 작업을 만드는 손 쉬운 방법

     async 함수를 통해서 손쉽게 비동기 작업을 할 수 있다. 아까 promise 생성자를 통해서 만들어진 promise 객체를 리턴하는 함수를 async 함수로 변경해본다.

    /* function findNumber(number) {
      return new Promise((resolve, reject) => {
        if (number < 10) reject(`오류: ${number}은 최소값보다 작습니다.`);
        resolve(number)
      })
    } */
    
    async function findNumber(number) {
    	if (number<10) return `오류: ${number}은 최소값보다 작습니다.`
    	return number
    }
    
    const promise1 = findNumber(3)
    promise1
      .then((number) => {
        console.log(100 * number)
      })
      .catch((error) => {
        console.log(error)
      })
    
    const promise2 = findNumber(100)
    promise2
      .then((number) => {
        console.log(100 * number)
      })
      .catch((error) => {
        console.log(error)
      })

    놀랍게도 결과는 같다. 즉, async 함수의 리턴 값은 무조건 Promise이다.

     

    Await - Promise가 끝날때까지 기다리거라

     await은 wait 하라는 의미처럼 보인다. 그렇다. promise가 rejected 상태이든, fulfilled 상태이든 상관없이 무조건 끝날 때 까지 기다리는 함수이다. 또한, await은 async함수 내부에서만 쓸 수 있다. 따라서, await의 특성은 다음과 같이 정리할 수 있다.

    1. 문법적으로 await [[Promise 객체]] 이렇게 사용한다.
    2. await은 Promise가 resolve한 값을 리턴한다.
    3. ⇒ 그렇다면 reject한 값은요? 이러한 값은 try-catch 구문을 통해 예외처리를 해준다.

    [참고]

    [책] 모던 자바스크립트 입문 - 이소 히로시 (길벗 출판사)

    https://springfall.cc/post/7

     

    [Javascript] 비동기, Promise, async, await 확실하게 이해하기

    초보자 입장에서 헷갈리기 쉬운 자바스크립트의 Promise 에 대해 낱낱이 파헤칩니다. 더 나아가 async와 await을 올바르게 사용하는 법까지 소개합니다.

    springfall.cc

     

Designed by Tistory.