Archive

[JS] 비동기 / Promise / async.await

manon_e 2022. 1. 6. 18:14
반응형

 

 

     


     

     

     

     

     


    웹 브라우저?

     

     

     

    🔻  웹 브라우저?

     

     : 서버에서 받아온 HTML, CSS, JS를 실행시켜주는 프로그램이다.

       브라우저는 자바스크립트를 실행하는 과정이 있다. 

     

       브라우저는 C++이라는 언어로 코드가 짜져있는데, 브라우저는 실행해야할 자바스크립트 코드를 발견하면

       C++ 언어로 만들어둔 stack에 넣어서 돌린다.

     

      stack은 다 집어넣고 맨 윗줄부터 하나하나 실행시키는 공간이다.

      하지만, 서버로의 ajax 요청, eventlistener, setTImeout 이런 코드들은 코드를 처리하기까지 시간이 오래걸린다.

      그래서 이런코드들은 stack에 쌓아서 실행하지않고, Queue라는 곳에 집어넣고 기다렸다가

      stack이 비어있을 때 차례로 Queue에서 stack으로 집어넣어서 실행해준다.

     

      따라서, stack을 바쁘게 만들면 setTimeout 이런 코드들은 실행이 불가능하다.

     

     

     

     

     

    🤷🏻‍♀️  시간이 오래 걸리는 작업을 꼭 해야한다면 ?

     

      1. setTimeout을 이용한다.

         작업을 0초마다 쪼개서 실행하게 한다. 그러면 0초마다 Queue로 보내기때문에 그 사이사이 사용자의 

         eventlistener이런 코드가 실행가능하게된다. ( 0초로 실행해도 4ms로 동작한다. 최소시간이 4ms )

     

     

      2. web worker를 이용한다.

        다른 js파일을 이용해서 오래걸리는 작업을 따로 작동시키고 그게 완료되면 값을 가져오라고 명령한다.

    (메인 js 파일)
    var myWorker = new Worker('worker.js'); 
    
    w.onmessage = function(e){
      console.log(e.data) //이러면 1 나올듯
    };
    (worker.js 파일)
    
    var i = 0;
    postMessage(i + 1); //postMessage라는 특별한 함수가 있음

    이런식으로 셋팅하면 worker.js에서 작업완료 시 postMessage() 이렇게 실행하면 다른 파일로 완료된 결과값을 전달해줄 수 있다.

    이러면 stack이 바빠지지않는다.

     

     

     

     

     

     


     

    동기? 비동기?

     

     

     

     🤷🏻‍♀️ 동기식 처리?

        : 동기식 처리는 한번에 코드 한줄씩 차례로 실행되는 것이다.

          위에서 설명된 웹브라우저의 stack이라는 코드실행공간에서 자바스크립트는 동기적으로 처리된다.

     

          but, 비동기처리 (asynchronous)가되는 특수한 함수들 때문에 가끔 비동기적 실행이 된다.

     

     

     

    console.log(1);
    setTimeout(()=>{ console.log(2) }, 1000 };
    console.log(3);
    
    //출력
    1
    3
    2

     

      setTimeout()이라는 함수는 Queue로 들어가서 제쳐두고, 다른 코드부터 실행되므로 1-3-2순서로 출력된다.

    이런 처리방식을 비동기라고 한다. ( 오래걸리는 작업이 있으면 제껴두고 다른거부터 처리 )

     

    자바스크립트 언어자체는 동기식 처리가 되지만,

    Web API와 연관된 특수한 함수들을 쓰면 작업이 오래걸리 때 다른것부터 실행이 가능하다.

    ( Web API에 오래걸리는 작업들을 넣어놓고 빨리 처리되는 함수들 먼저 실행한다. )

     

     

     

     


    Callback함수

     

     

     

    🤷🏻‍♀️ 비동기상황에서 순차적으로 코드를 실행하고 싶다면?

        :  콜백함수를 활용한다. 

           콜백함수는 간단하게 함수안에 들어가는 함수를 전부 콜백함수라 생각할 수 있다.

     

     

    function 첫째함수 () {}
    
    function 둘째함수 () {}
    
    //순서대로 실행하고 싶을때 setTimeout같은 함수가 있으면 이런식으로 실행시 실패한다.
    첫째함수()
    둘째함수()
    
    //이럴때 콜백함수로 실행하면 순차적으로 실행이 가능하다.
    첫째함수(둘째함수)

     

     

    callback 함수

    function 첫째함수(둘째) {
     console.log(1);
     둘째();
    }
    
    function 둘째함수(){
     console.log(2);
    }
    
    첫째함수(둘째함수);

     

     

    callback 함수의 문제점

    - 순차적으로 실행하고싶은 코드가 여러개라면 코드가 지저분해진다.

       이러한 문제점을 개선한 것이 promise.

    첫째함수(function(){
      둘째함수(function() {
        셋째함수(function() {
        
        })
      })
    });

     

     

     

     

     

     


     

     

     

     

     

    Promise

     

     

     

    Promise

    : 자바스크립트의 새로운 기능이라기보다는 코드/함수 디자인 패턴이다.

     (동기를 비동기로 만들어주는 코드가 아니고, 디자인 패턴)

     

     

    let 프로미스 = new Promise(성공, 실패) {
      let 어려운 연산 = 1+1;
      //연산 후 실행하고 싶은 코드를 적는다. 성공() 적으면 .then에 있는, 실패() 적으면 .catch
      //성공()
      //실패()
    };
    
    프로미스
    .then(()=> {})    //성공시 실행되는 코드
    .catch(()=> {})   //실패시 실행되는 코드

    new Promise()로 생성된 변수를 콘솔창에 출력해보면 현재상태를 알 수 있다.

    [ 3가지 상태 ]

    성공/실패 판정 전에는 pending

    성공 후에는 resolved

    실패 후에는 rejected

     

     

     

     

    프로미스안에 콜백함수 실행

    성공 했을 때 then() 함수내의 코드를 실행

    실패했을 경우에는 catch( ) 함수내의 코드를 실행한다.  (callback함수와 다른점)

     

     

     

    콜백대신 쓰는이유?

    - 콜백보다 코드가 깔끔하다.

    - 성공/실패의 경우 각각 다른 코드가 실행가능하다.

     

     

     

    [예시]

    > setTimeout 예시

     1초후에 성공하는 promise - 성공시 특정코드 실행

    let 프로미스 = new Promise(function (성공, 실패) {
      setTimeout(() => {
        성공();
      }, 1000);
    });
    
    프로미스
      .then(() => {
        console.log("success");
      })
      .catch(() => {
        console.log("fail");
      });

     

     

     

     

     


     

     

     

     

     

    async / await

     

     

     

    async를 사용하면 promise object가 저절로 생긴다.

    ( async는 함수 앞에만 붙일 수 있다. )

    async function 더하기(){
      return 1 + 1 
    }
    
    //async를 붙였으니까 then 사용 가능
    //return 결과값 then 함수에서 파라미터로 넣어주면 사용가능
    더하기().then(function(결과){
      console.log(결과)
    });

     

     

     

    then 대신 await를 async function 안에서 쓸 수 있다.

    await를 붙여주는 함수가 다 끝날 때 까지 기다려준다.

    async function 더하기() {
      let 연산 = new Promise((성공, 실패) => {
        let 결과 = 1 + 1;
        성공(100);
      });
    
      let 결과 = await 연산    //연산 promise를 기다린다음에 완료되면 결과를 변수에 담아라.
      console.log(결과)
      
      //아래의 promise코드와 위의 await는 같은 역할을 한다.
      //promise.then (()=> {
      //console.log('결과')
    }
    더하기()

     

     

     

     

    await는 실패하면 에러가 나고 코드가 멈춘다.

    promise가 실패할 경우 코드실행을 멈추고 싶지 않으면 try catch를 사용한다.

    try{}안의 코드가 에러나고 멈출경우, 대신 catch{}내부의 코드를 실행한다.

    try { 이걸해보고 에러나면 } catch { 이걸 실행해 }

    async function 연산 () {
     let 프로미스 = new Promise ((성공, 실패)=> {
     	let 연산 = 1+1;
        성공(연산)
     });
     
     try {
     	let 결과 = await 프로미스;
        console.log(결과);
     } catch {
        console.log('실패')
     }
    }

     

     

     

    반응형

    'Archive' 카테고리의 다른 글

    [TS] declare / d.ts / index signatures  (0) 2022.01.13
    [TS] React  (0) 2022.01.12
    [GIT] Github 잔디 안심어지는 현상  (0) 2022.01.05
    [JS] getter,setter / import,export  (0) 2022.01.05
    [TS] Private / Static / Generic 등  (0) 2022.01.05