ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 동기, 비동기
    JavaScript 2020. 5. 27. 21:39

    동기, 비동기의 개념을 알기 위해서는 먼저 콜백함수에 대한 이해가 필요하다.

     

    콜백함수

    - 아래에서 보면, 다른 함수(A)의 전달인자로 넘겨주는 함수(B) 즉, B가 A의 콜백함수다.

    function B(){
      console.log('called at the back!');
    }
    
    function A(callback){
      callback();
    }
    
    A(B);

    그런데 이때 함수 A는 콜백함수 B를 필요에 따라 즉시 실행할 수도 있고(동기적), 나중에 실행할 수도(비동기적) 있다.

     

    - 동기(Synchronous) : 요청에 대한 결과가 동시에 일어난다

    - 비동기(Asynchronous) : 요청에 대한 결과가 동시에 일어나지 않는다

     

    아래는 동기적인 실행에 대한 예시

    function waitSync(ms){
      var start = Date.now();
      var now = start;
      while(now - start < ms){
        now = Date.now();
      }
    }
    // 위 함수는 일단 동기적으로 딜레이 시켜주는 함수라고 생각하고 넘어가자.
    
    function drink(person, coffee){
        console.log(person + '는 ' + coffee + '를 마십니다');
    }
    
    function orderCoffeeSync(coffee){
        console.log(coffee + '가 접수되었습니다');
        waitSync(4000);
        return coffee; // 콘솔창에 접수 메시지 출력 후 4초간 멈춘 뒤 전달인자를 반환한다.
    }
    
    let customers = [{
      name: 'Steve',
      request: '카페라떼'
    }, {
      name: 'John',
      request: '아메리카노'
    }];
    
    customers.forEach(function(customer){
      let coffee = orderCoffeeSync(customer.request);
      // 콘솔창에 접수 메시지 출력 후 4초간 멈춘 뒤 customer.request를 반환, 변수 coffee에 담는다.
      drink(customer.name, coffee); // 곧바로 drink함수를 실행한다
    });
    
    /*결과
    카페라떼가 접수되었습니다(메시지 출력 후 4초간 멈춤)
    Steve는 카페라떼를 마십니다
    아메리카노가 접수되었습니다(메시지 출력 후 4초간 멈춤)
    John은 아메리카노를 마십니다
    */

    위에서 forEach메서드의 콜백함수는 customers의 모든 요소에 접근하면서 반복 실행되는데, 내부 함수(drink)를 실행하기 전에 4초간 멈춘다. 즉, customers의  한 요소를 통과하는데만 4초가 걸린다.

     

    아래는 비동기적인 실행의 예시

    function waitAsync(callback, ms){
      setTimeout(callback, ms); // setTimeout : 타이머가 만료된 뒤 함수나 지정된 코드를 실행하는 타이머를 설정한다.
    }
    
    function drink(person, coffee){
      console.log(person + '는 ' + coffee + '를 마십니다');
    }
    
    function orderCoffeeAsync(menu, callback){
      console.log(menu + '가 접수되었습니다');
      waitAsync(function(){
        callback(menu);
      }, 4000);  //콘솔창에 접수 메시지 출력 후 4초 뒤에 callback함수를 실행한다
    }
    
    let customers = [{
      name: 'Bruce',
      request: '카페라떼'
    },{
      name: 'Sarah',
      request: '아메리카노'
    }];
    
    
    customers.forEach(function(customer){
      orderCoffeeAsync(customer.request, function(coffee){
        drink(customer.name, coffee);
        // 콘솔창에 접수 메시지 출력 후 4초 뒤에, drink함수를 실행하는 함수를 실행한다
      });
    });
    /* 결과
    카페라떼가 접수되었습니다
    아메리카노가 접수되었습니다 -> 여기까지는 바로바로 실행한다
    Bruce는 카페라떼를 마십니다 -> 여기부터는 4초 뒤에 실행 된다
    Sarah는 아메리카노를 마십니다
    */

    위에서 함수표현식으로 코딩된 forEach메서드의 인자로 주어진 콜백함수는, customers의 모든 요소를 순회하면서 반복 실행되는데, 각 요소마다 자신의 내부 함수 orderCoffeeAsync를 실행시키고, orderCoffeeAsync는 4초 후에 orderCoffeeAsync의 콜백함수 drink를 실행하도록 타이머를 설정한다. 즉, 함수 drink가 customers의 한 요소에 실행되기까지는 4초가 걸리지만, forEach메서드의 콜백함수가 그동안 다른 작업을 하지 않고 멈춰있는 것은 아니며, 타이머가 돌아가는 동안 다음 요소로 넘어가서 실행되고 있다.

    댓글

Designed by Tistory.