ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2023 - 06 - 12 동기 (Sync) & 비동기 (Async) 모델, Non-Blocking 모델, 프로미스 Promise, .then, Promise .catch,
    Today I Learned/TIL 06 2023. 6. 11. 10:32

    오늘 할일

    노드 강의듣기

     

    오늘 배운 것

    동기적 모델, 비동기적 모델

     

    1. 동기적 모델 Sync :  먼저 실행된 코드의 결과가 나올때까지 대기함.

    Ex) 놀이기구에서, 정원이 30명이라고 치면 놀이기구를 한번 태우는데 5분이 걸리면 다음 30명의 대기자들은 5분이 지나야 놀이기구를 탈 수 있다. 즉 놀이기구의 탑승과 하차가 동기적으로 관리된다.

     

    async function main() {
        function first(){
            console.log("2. setTimeout이 실행되었습니다.")
        }
        console.log("1. 코드가 실행되었습니다.")
        setTimeout(first, 1000); // 1초뒤에 setTimeout함수를 실행해라
        console.log("3. 코드가 종료되었습니다.")
    }   
    main();

    동기적인 모델(Sync)의 순서
    동기적인 순서는 위에서부터 아래대로 순차적으로 진행이 된다.
    동기적인 Blocking 모델의 경우 1번 => (1초뒤) 2번 => 3번 순서

     

    2. 비동기적 모델 Async : 실행된 순서와 관계없이 결과가 나온다.

    맛집에서, 누가 먼저 입장했든 관계없이, 밥을 다 먹은 사람이 먼저 나온다. 즉 맛집에서의 입장과 퇴장이 동기적으로 관리된다.



    비동기적 모델(Async)의 순서
    자바스크립트는 Async모델이고, Non-Blocking (제어권을 다른곳에 넘김) 모델임.
    순서는 1번 => 3번 => (1초 뒤) 2번

     

    *Non-Blocking Model이란, 코드의 실행이 끝나지 않아도 실행 제어권을 다른 곳에 넘겨서 다음 코드가 실행될 수 있는 것.

    반면에 Blocking Model이란, 코드의 실행이 끝나기 전까지 실행 제어권을 다른 곳에 넘기지 않아 다른 작업을 하지 못하고 대기하는 것,

     

    function first () {
        console.log('first');
    }
    setTimeout (first, 1000);
    
    console.log('middle')
    console.log('last')

    순서 middle => last => (1초 뒤) 'first'

     


    3. 프로미스 (promise) : 비동기적 언어인 자바스크립트를, 동기로 처리할 수 있게 돕는 객체 유형.

    Promise 생성자 인터페이스
    
    new Promise (executor);
    new Promise ((resolve, reject) => {
        //명령문
    })



    executor에는 함수만 올 수 있고, 인자로는 resolve, reject가 온다. 

    executor는 Promise의 실행함수라서, Promise가 만들어질때 자동실행됨.
    Promise가 정상적으로 완료되면 resolve를 호출, 에러 발생시 reject 호출.

     


    생성자 (constructor)함수 (new~) : 객체(Object)를 생성하는 함수. Promise 또한 객체로 구성되어 있기 때문에 생성자 함수를 이용해 Promise를 선언함.

    const timerPromise = new Promise((resolve, reject) => { 
        // 이곳에 정의된 함수가 executor
        setTimeout(() => {
                console.log('First');
                      resolve();
              }, 1000);
      });
      
      // 이 시점에서 timerPromise는 뒤에 then이 붙었으므로, Fulfilled Promise라고 부를 수 있다.
      
      timerPromise.then(() => {
              console.log('Middle');
              console.log('Last');
      });
      
      // Print: First
      // Middle
      // Last



    생성자 함수 new ~

    async function main() {
        function printFunc(){
            console.log("printFunc가 실행되었습니다.")
        }
        const obj = new Object();
        const prom = new Promise(printFunc)
    }
    main();



    함수 변수값 앞에 new가 있으면 새로운것을 생성한다는 뜻
    new Promise를 생성하게 되었을 떄, 성공적으로 되었을때 printFunc 실행됨.
    생성자 함수를 통해 객체 new Object(); 를 생성하고 new Promise 또한 생성함.

    Promise의 상태
    Promise는 대기(Pending)상태가 아니라면, Promise의 연산이 이미 끝난 상태.


    대기 (Pending) :이행되거나 거부되지 않은 초기상태
    이행 (Fulfilled) : 연산 성공
    거부 (Rejected) :연산 실패

    // -----------------------------------------------------------

    3 Promise.then

    Promise가 만들어질때 executor가 실행되며, executor에서 resolve함수가 호출되기 전까지 .then(...)안의 코드를 실행하지 않는다. resolve가 실행되어 코드가 성공적으로 실행될 때, then (resolvePromise.then())을 통해 실제로 Promise가 Fulfilled 되었을 때 실행되는 방식임.


    then()은 resolve를 통해 fulfilled 상태가 되었을 때 실행되는 구문임.
    이렇게 executor가 실행되어 resolve된 프로미스를 Fulfilled Promise라고 부른다.

    순서 
    new Promise 생성 => 

    executor 실행 (중괄호에 정의된 함수, 여기선 setTimeout()) => 

    Promise가 Fulfilled 되면 (충족되면) resolve함수 호출 => 

    then() 메서드 실행


    const resolvePromise = new Promise((resolve, reject) => {
        setTimeout(() => {
            // 1초 뒤에 setTimeout에 있는 코드를 실행하라.
          console.log('First');
          resolve('Resolve!'); // resolve를 실행할 때, 안에 데이터를 넣어줄 수 있습니다.
        }, 1000);
      });
      
      resolvePromise.then((data) => {
        console.log('Middle');
        console.log('Last');
        console.log(data);
      })
      
      Print: First -> 1초 뒤에 출력됩니다.
      Middle
      Last
      Resolve! 
      (resolve를 통해 'Resolve!'를 .then(data)에 전달, 마지막 console.log(data)는 'Resolve!' 출력.





    4. Promise.catch
    new Promise 실행 시 resolve인 경우 => .then() 실행. 
    reject인 경우 => .catch 실행.

    const errorPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
                console.log('First');
                      reject('Error!!'); 
                      // 직접 reject를 실행하면 프로미스에서 에러가 발생한것으로 간주됩니다.
              }, 1000);
      });
      
      errorPromise
      .then(() => {
              console.log('Middle');
              console.log('Last');
      })
      .catch((error) => {
              console.log('에러 발생!', error);
      });




      1초 뒤 'First' 출력.
      동시에 Print: '에러 발생! Error!!' 출력. 여기서 Error!!는 reject함수에서 전달된 string(문자열)

    -----------------------------------------------------------

    5. Promise.then 더 알아보기

    Promise에서 resolve된 값 이용하기
    
    const firstPromise = new Promise ((resolve, reject) => {
        resolve('First')
    });
    firstPromise.then((value) => {
        console.log(value);
    })
    //print: 'First'



    위의 식은 아래와 같다.
    프로미스가 값을 반환하는 경우, 반환되는 값은 항상 프로미스로 감싸져 있다.

    Promise를 바로 resolve하면 바로 .then()으로 resolve 결과값인 문자열 'First' 출력됨
    
    const secondPromise = Promise.resolve('First');
    
    secondPromise.then((value) => {
        console.log(value);
    })
    //print: 'First'



    아래처럼 Promise.then으로 함수형 프로그래밍도 가능.
    이것이 가능한 이유는 console.log뒤에 괄호 안쓰고 함수 자체를 그대로 then에 넘겼기 때문

    const thirdPromise = Promise.resolve('First');
    thirdPromise.then(console.log)
    //print: 'First'




    6. 비동기 함수 (Async function)
    1. 비동기함수의 결과값은 항상 Promise 객체로 resolve된다
    2. 비동기 함수 안에서만 오직 await 연산자를 사용할 수 있다.

    // 비동기+일반함수
    async function 함수이름(){}
    
    // 비동기+익명함수
    async function() {}
    
    // 비동기+화살표함수
    async () => {}



    new Promise(executor)코드로 Promise를 직접 생성하면 executor가 바로 실행되는것과 달리
    비동기 함수는 함수가 실행되기 전까지 Promise를 생성하지 않는다.

    await 연산자
    await 연산자를 사용하면 Promise가 fulfill 상태가 되거나 rejected될 때까지 함수의 실행을 중단하고 기다릴 수 있다.
    '값'에는 Promise가 아닌 다른 값도 들어갈 수 있다. Promise가 아니라면, await은 기다리지 않고 해당 값 자체를 그대로 반환한다.

    setTimeoutFunc함수를 실행했을때 특정 시간(time)을 입력받게 되고 그다음에 Promise가 리턴됨
    Promise가 실행되고 나서 입력받은 time만큼의 시간이 지났을 때 console.log 작동

    function setTimeoutFunc(time){
        return new Promise((resolve, reject) => {
            setTimeout (() => {
                console.log(time, "에 해당하는 시간이 지났습니다.")
                resolve();
            }, time)
        })
    }
    async function main(){
    
        console.log("시작되었습니다.");
        setTimeout(1000); 
        console.log("종료되었습니다.");
    }
    main();



    비동기함수

    시작되었습니다 => 종료되었습니다 => (1초뒤) 1000에 해당하는 시간이 지났습니다

    그런데 만일 아래처럼, setTimeout에 await이 걸려있는 경우


    function setTimeoutFunc(time){
        return new Promise((resolve, reject) => {
            setTimeout (() => {
                console.log(time, "에 해당하는 시간이 지났습니다.")
                resolve();
            }, time)
        })
    }
    async function main(){
    
        console.log("시작되었습니다.");
        await setTimeout(1000); 
        console.log("종료되었습니다.");
    }
    main();



    시작되었습니다 => (1초뒤) "1000에 해당하는 시간이 지났습니다" => "종료되었습니다"
    await은 결과값으로 resolve나 reject가 실행되기 전까지는 대기하도록 함.

     

     

    댓글

Designed by Tistory.