동기와 비동기, 그리고 Promise

KIP·2022년 4월 11일
0

동기 (synchronous) - JS

js는 싱글스레드 작업수행방식
먼저 작성된 코드를 다 실행 후 뒤에 작성된 코드를 실행(블로킹 방식)

한 task마다 시간이 길때 흐름이 늦어지는 문제가 발생

따라서, mulit-thread의 방식으로 여러가지의 thread를 사용해 비동기 작업처럼 보이게 할 수 있음.

Multi-thread 와 비동기는 다른의미인데 나는 아직 잘 모르겠다..

Multi-thread

non-blocking방식으로 여러개의 작업을 동시에 실행하는 방식 (단일 task마다 callback을 수행시킴)

Memory Heap과 Call stack

위의 그림이 JS가 동기와 비동기를 구분하는 법이다(js engine)

동기의 예제

function A(){
     return 1;
 }

 function B(){
     return A() + 1;
 }

 function C(){
     return B() +1;
 }
 console.log(C())

이와 같은 코드는 실제 call stack에 Main Context => C() => B() => A()로 실행된다.
그 후 반대로 종료되면서 Context가 종료된 후 callStack이 종료된다.

비동기 예제

function async(a,b,cb){
    console.log('hi')
    setTimeout(() => {
        const res2 = a+b;
        cb(res2)
    },3000)
}

async(1,3, (res) =>{
    console.log("res===>" +res)
})

setTimeout비동기를 만들어주는 함수.
cb라는 callback함수를 만들어 3초 뒤에 async()가 실행된다.

비동기함수에는 web Apis, callback Queue를 같이 알아야 하는데,
처음 동기와 프로세스와 같이 Context -> a() -> setTimeout()+cb()을 호출한다.
이때 setTimeout은 cb()를 같이 넣어서 호출 후는 web Apis로 빠진다.
따라서 Web Apis로 가있동안 호출되었던 a()는 종료되고 cb()은 callback Queue로 간다. 그 후 event loop를 따라 Main Context에 남은게 있는지 확인 후 cb()를 실행한다. 아직 완벽하지 않은 개념이다..

Promise

callback함수의 지옥

 function a (a, b, cb) {
     setTimeout(() => {       
        const res = a+b;
         cb(res)    
         return res;
     }, 1000);
 }
 console.log("코드 끝")

 function b ( a ,cb1){
     setTimeout(() =>{
        const res1 = a * 2;
        cb1(res1)
         return res1;
     }, 100);
    
 }
 function c (a, cb){
     setTimeout(() =>{
         const res = a * -1;
         cb(res)
         return res;
     }, 3000);
 }
 a(4,5,(a_res) =>{ // a호출
     console.log("a" +a_res);
     b(a_res,(b_res)=>{  // b호출 후 매개변수 => a리턴 값
         console.log("b"+b_res)
         c(b_res,(c_res) =>{ //c호출 후 매개변서 =>b 리턴 값
            console.log("c"+ c_res)
         });
     });
 }); 

와 같이 callback을 겨우 3번 사용했음에도 지옥과 같이 길다.
이것을 해결하기 위해 생긴 것이 Promise다

이처럼 비동기 작업이 가질 수 있는 3가지 상태로 PENDING, RESOLVED, REJECTED가 있다.

Promoise 예시(2가지)

  function Promise(number){
     const executor = (resolve, reject) => {
         setTimeout(() =>{
            if(typeof number === 'number'){ //숫자인지 판별
                //성공 -> resolve
                resolve(number >= 0 ? '양수': '음수') //삼항 연산자
                console.log(number);
            }else{
                //실패
                reject("주어진 값이 숫자가 아니다.")
            }
         }, 1000)
     }
    /* async 선언하면서 promise객체 생성.
     실행자 힘수인 executor * 
    const asyncTask = new Promise(executor);
    return asyncTask;
 }
    const res = Promise(10) // number의 타입을 아무거나 입력
    res
        .then((res) => 
        {console.log("reslove==>"+ res)}
        )
        .catch((err) => 
        {console.log("reject ==> "+err)}
        )
 function a(a,b){
        /* 이게 const executorA = new Promise(executorA)와 같다. */
        return new Promise((resolve,reject) =>{
            setTimeout(() =>{
                const res = a+b;
               resolve(res)
            },1000)
        })
    }
    function b(a){
        return new Promise((resolve,reject) =>{
            setTimeout(() =>{
                const res = a *2;
                resolve(res)
            },2000)
        }
    }
    function c(a){
        return new Promise((resolve,reject)=>{
            setTimeout(() =>{
                const res = a * -1;
                resolve(res)
            },3000)
        }) 
    }
    //실행부
    const ProimseA = a(5,4) //a함수 호출 후 PromiseA라는 상수 선언
   .then((a_res) =>{ //then으로 나눌 수 있다.
       console.log('a'+a_res);
       return b(a_res);  //b함수 반환
   });
   console.log("테스트테스트") //중간에 console.log를 실행시켜도 상관없음.
   console.log("테스트테스트")
   console.log("테스트테스트")
   //다시 PromiseA 를 받아서 작업.
   ProimseA.then((b_res)=>{ 
       console.log('b'+ b_res)
       return c(b_res); //c함수 반환
   })
   .then((c_res)=>{
       console.log('c'+ c_res)
   })

0개의 댓글