1. 콜백함수

(1) 제어권

  1. 호출 시점

  2. 인자

  3. this

(2) 콜백 함수는 함수다

(3) 콜백 함수 내부의 this에 다른 값 바인딩하기

(4) 콜백 지옥과 비동기 제어

  1. 콜백 지옥

  2. 동기 vs 비동기

    1. 동기 : synchronous

      1. 현재 실행중인 코드가 끝나야 다음 코드를 실행하는 방식.
      2. CPU의 계산에 의해 즉시 처리가 가능한 대부분의 코드는 동기적 코드이다.
      3. 계산이 복잡해서 CPU가 계산하는 데 오래 걸리는 코드.
    2. 비동기 : a + synchronous ⇒ async라고들 흔히 부르죠

      1. 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가는 방식

      2. setTimeout, addEventListner 등

      3. 별도의 요청, 실행 대기, 보류 등과 관련된 코드는 모두 비동기적 코드

        (출처 : https://velog.io/@mrbartrns/til-16-asynchronous-of-js)

        (출처 : https://velog.io/@mrbartrns/til-16-asynchronous-of-js)

  3. 콜백 지옥의 예시와 해결방안

    (1) 첫번째 해결 방법 - 기명 함수로 변환

    가독성은 좋아졌으나, 이런식으로 이름을 다 붙히는 건 근본적인 해결책은 아닌 것 같다.

    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, '에스프레소');
    

    (2) 비동기 작업의 동기적 표현하기.

    1. Promise (1)

      Promise 간단 설명

      • new 연산자로 호출한 Promise의 인자로 넘어가는 콜백은 바로 실행된다.
      • 그 내부의 resolve(또는 reject) 함수를 호출하는 구문이 있을 경우, reslove(또는 reject) 둘 중 하나가 실행되기 전까지는 다음(then), 오류(catch)로 넘어가지 않는다.
      • 비동기 작업이 완료될 때 비로소 resolve, reject를 호출한다.
      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);
      	});
      });
      
    2. Promise (2) - Closer

      • 반복 부분을 재귀적으로 표현한 코드. trigger를 걸어주기 위해 클로저 개념이 나온다.

        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('에스프레소')()
        	.then(addCoffee('아메리카노'))
        	.then(addCoffee('카페모카'))
        	.then(addCoffee('카페라떼'));
        
    3. Promise (3) - Generator

      <aside> 💡 이터러블 객체 (Iterable)

      생소한 제너레이터 문법이다.

      *가 붙은 함수가 제너레이터 함수로 실행하면 Iterator 객체가 반환된다. (next()를 가지고 있음.)

      iterator는 객체가 next메서드로 순환할 수 있는 개체로, next 메서드 호출 시, Generator 함수 내부에서 가장 먼저 등장하는 yield에서 stop이후 다시 메서드를 호출하면 멈췄던 부분 → 그 다음의 yield까지 실행 후 stop한다.

      즉, 비동기 작업이 완료되는 시점마다 next 메서드를 호출해주면 Generator 함수 내부소스가 위에서 아래로 순차적으로 진행된다.

      </aside>