sitelink1 https://blog.naver.com/ksyooon0718/222218782502 
sitelink2  
sitelink3  
sitelink4  
extra_vars4  
extra_vars5  
extra_vars6  

* 스크랩 내용

 

05. 콜백지옥과 비동기제어

 

- 콜백지옥은 콜백함수를 익명함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 깊어지는 현상

- 주로 이벤트처리나 서버 통신과 같이 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장함

- 동기적인 코드는 현재 실행중인 코드가 완료된 후에야 다음 코드를 실행하는 방식 

- 비동기적인 코드는 현재 실행중인 코드 완료 여부와 무관하게 즉시 다음 코드로 넘어감 

- 사용자의 요청에 의해 특정 시간이 경과되기 전까지 어떤 함수의 실행을 보류한다거나(setTimeout)

- 사용자의 직접적인 개입이 있을 때 함수를 실행하도록 대기한다거나 (addEventListener)

- 웹브라우저 자체가 아닌 별도의 대상에 무언가를 요청하고 응답이 왔을 때 함수를 실행하도록 대기하는 (XMLGttpRequest)

- 이런 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 비동기적인 코드

 

// setTimeout 문법

var timeoutID = window.setTimeout(func[, delay, param1, param2, ...]);

var timeoutID = window.setTimeout(code[, delay]);

window.setTimeout(function, milliseconds);

// 예제 4-12

setTimeout(function(name){

  var coffeeList = name;

  console.log(coffeeList);

 

  setTimeout(function(name){

    coffeeList += ',' + name;

    console.log(coffeeList);

    

    setTimeout(function(name){

      coffeeList += ',' + name;

      console.log(coffeeList);

     

      setTimeout(function(name){

        coffeeList += ',' + name;

        console.log(coffeeList);

      },500,'카페라떼');

    },500,'카페모카');

  },500,'아메리카노');

},500,'에스프레소');

 

// 에스프레소

// 에스프레소, 아메리카노

// 에스프레소, 아메리카노, 카페모카

// 에스프레소, 아메리카노, 카페모카, 카페라떼

// 문제점 : 들여쓰기 수준이 깊어졌으며, 값이 전달되는 순서가 아래에서 위로 향하고 있어 어색하게 느껴짐

// 예제 4-13 - 기명함수로 변환

var coffeeList = '';

 

var addEspresso = function(name){

  coffeeList = name;

  console.log(coffeeList);

  setTimeout(addAmericano, 500, '아메리카노');

};

var addAmericano = function(name){

  coffeeList += ',' + name;

  console.log(coffeeList);

  setTimeout(addMocha, 500, '카페모카');

};

var addMocha = function(name){

  coffeeList += ',' + name;

  console.log(coffeeList);

  setTimeout(addLatte, 500, '카페라떼');

};

var addLatte = function(name){

  coffeeList += ',' + name;

  console.log(coffeeList);

};

  setTimeout(addEspresso, 500, '에스프레소');

 

// 가독성은 좋아졌지만, 일회성 함수라는 것이 단점

 

- setTimeout을 변수에 넣는 과정에서 메서드가 실행된다고 배웠는데, 위 예제에서 실행되지 않는 이유 

=> setTimeout을 함수안에 넣었기 때문에 함수를 실행하지 않는 이상 별도로 실행되지 않는다

 

// 예제 4-14 비동기 작업의 동기적 표현 - Promise

new Promise(function(resolve){

  setTimeout(function(){

    var name = '에스프레소';

    console.log(name);

    resolve(name);

},500);

}).then(function(prevName){

  return new Promise (function(resolve){

    setTimeout(function(){

      var name = prevName + '아메리카노';

      console.log(name);

      resolve(name);

    },500);

  });

}).then(function(prevName){

  return new Promise (function(resolve){

    setTimeout(function(){

      var name = prevName + '카페모카';

      console.log(name);

      resolve(name);

    },500);

  });

}).then(function(prevName){

  return new Promise (function(resolve){

    setTimeout(function(){

      var name = prevName + '카페모카';

      console.log(name);

      resolve(name);

    },500);

  });

 

- resolve 또는 reject 함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 then 또는 오류구문(catch)으로 넘어가지 않음

 

// 예제 4-15 비동기작업의 동기적 표현 - Promise2

var addCoffee = function(name) {

  return function(prevName) {

    return new Promise(function(resolve){

      setTimeout(function(){

        var newName = prevName ? (prevName + ',' + name) : name;

        console.log(newName);

        resolve(newName);

      },500);

    });

  };

};

addCoffee('에스프레소')()          // 함수 addCoffee 안에 return값으로 내부함수가 있는구조기 때문에 함수 실행을 두번한다 

  .then(addCoffee('아메리카노'))

  .then(addCoffee('카페모카'))

  .then(addCoffee('카페라떼'));

 

- 함수 addCoffee안에 return값으로 내부함수가 있는 구조기 때문에 함수 실행을 두번한다 

- 이후 then의 두번째 함수의 인자로 이전 resolve값이 온다

 

// 예제 4-16 비동기작업의 동기적표현 - Generator

var addCoffee = function (prevName, name){

  setTimeout(function(){

    coffeeMaker.next(prevName? prevName + ',' + name : name);

  },500);

};

var coffeeGenerator = function* () {

  var espresso = yield addCoffee('', '에스프레소');

  console.log(espresso);

  var americano = yield addCoffee(espresso, '아메리카노');

  console.log(americano);

  var mocha = yield addCoffee(americano, '카페모카');

  console.log(mocha);

  var latte = yield addCoffee(mocha, '카페라떼');

  console.log(latte);

};

var coffeeMaker = coffeeGenerator();

coffeeMaker.next();  

 

- '*'이 붙은 함수가 Generator 함수

- 함수 실행시 Iterator가 반환되는데, Iterator는 next라는 메서드를 가지고 있음

- next메서드 호출시 가장 먼저 등장하는 yield에서 함수의 실행을 멈춤

- 이후 다시 next메서드를 호출하면 앞서 멈췄던 부분부터 시작해서 다음에 등장하는 yield에서 함수의 실행을 멈춤  

 

 

// 비동기작업의 동기적표현 - Promise+Async/await

var addCoffee = function(name){

  return new Promise(function(resolve){

    setTimeout(function(){

      resolve(name);

    },500);

  });

};

var coffeeMaker = async function(){

  var coffeeList = '';

  var _addCoffee = async function(name){

    coffeeList += (coffeeList ? ',' : '') + await addCoffee(name);

  };

  await _addCoffee('에스프레소');

  console.log(coffeeList);

  await _addCoffee('아메리카노');

  console.log(coffeeList);

  await _addCoffee('카페모카');

  console.log(coffeeList);

  await _addCoffee('카페라떼');

  console.log(coffeeList);

};

coffeeMaker();

 

- 비동기 작업을 수행하고자 하는 함수 앞에 async를 표기한다,

- 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await 표기하는 것만으로 뒤의 내용을 Promise로 자동전환되며, 

해당 내용이 resolve된 이후에야 다음으로 진행된다 ( Promise then과 흡사한 효과를 얻을 수 있다 )

 
 
 
 
 
 
 
 
* 본문 캡춰
2021-02-18 오전 7-18-14.jpg