JavaScript - 콜백 함수

euNung·2022년 6월 26일
0

JavaScript

목록 보기
4/7
  • 콜백 함수
    : 다른 코드의 인자로 넘겨주는 함수

  • 예제) setInterval

    var count = 0;
     var cbFunc = function() {
        console.log(count);
        if (++count > 4) clearInterval(timer);
     };
        
     var timer = setInterval(cbFunc, 300);
    • setInterval 구조
      : setInveral을 실행하면 반복적으로 실행되는 내용 자체를 특정할 수 있는 고유한 ID 값 반환
      : 반복 실행되는 중간에 clearInterval(intervalId) 로 종료 할 수 있음
      var intervalId = scope.setInterval(func, delay[, param1, param2, ...]);
      // scope에는 Window 객체 또는 Worker의 인스턴스가 들어올 수 있음
      code 호출 주체 제어권
      cbFunc(); 사용자 사용자
      setInterval(cbFunc, 300); setInterval setInterval

  • 예제) Array.prototype.map

    var newArr = [10, 20, 30].map(fnction (currentValue, index) {
    	console.log(currentValue, index);
    	return currentValue + 5;
    });
    console.log(newArr);
    
     // 실행 결과
     // 10 0
     // 20 1
     // 30 2
     // [15, 25, 35]
    • map 메서드 구조
      : 첫 번째 인자로 callback 함수를 받고, 생략 가능한 두 번쨰 인자로 콜백 함수 내부에서 this로 인식할 대상을 특정 가능
      : thisArg를 생략할 경우에는 일반적인 함수와 마찬가지로 전역객체가 바인딩됨
      Array.prototype.map(callback[, thisArg])
      callback: function(currentValue, index, array)
  • 콜백 함수는 함수이므로 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출된다.

    var obj = {
     	vals: [1, 2, 3],
     	logValues: function(v, i) {
         	console.log(this, v, i);
       	}
     };
    obj.logValues(1, 2);				// { vals: [1, 2, 3], logValues: f } 1 2
    [4, 5, 6].forEach(obj.logValues);	// Window {...} 4 0
    									// Window {...} 5 1
    									// Window {...} 6 2
  • 콜백 함수 내부의 this에 다른 값 바인딩

    var obj1 = {
     	name: 'obj1',
     	func: function () {
         	console.log(this.name);
       	}
     };
    setTimeout(obj1.func.bind(obj1), 1000);
    
    var obj2 = { name: 'obj2' };
    setTimeout(obj1.func.bind(obj2), 1500);

  • 콜백 지옥
    : 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상
    : 주로 이벤트 처리나 서버 통신과 같이 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장

  • 비동기적인 코드
    : 현재 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가는 방식

    • 동기적인 코드
      : 현재 실행 중인 코드가 완료된 후에야 다음 코드를 실행하는 방식
  • 콜백 지옥을 해결하며 비동기적인 작업을 하기위해 ES6에서는 Promise, Gernerator 등이 도입됐고, ES2017에서는 async/await가 도입

    • Promise
      : new 연산자와 함께 호출한 Promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만 그 내부에 resole 또는 reject 함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 다음(then) 또는 우류 구문(catch)으로 넘어가지 않음
     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('카페라떼'))
    • Generator
      : Generator 함수를 실행하면 Iterator가 반환되는데, Iterator는 next라는 메서드를 가지고 있음
      : next 메서드를 호출하면 Generator 함수 내부에서 가장 먼저 등장하는 yield에서 함수의 실행을 멈춤
      : 이후 다시 next 메서드를 호출하면 앞서 멈췄던 부분부터 시작해서 그 다음에 등장하는 yield에서 함수의 실행을 멈춤
     var addCoffee = function (name) {
       return new Promise(function (resolve) {
         setTimeout(function() {
             coffeMaker.next(prevName ? (prevName + ', ' + name) : name);
       }, 500);
     };
    
     var coffeGenrator = 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();
     coffeMaker.next();
    • Promise + Async/await
      : 비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고, 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 표기
      : 뒤의 내용을 Promise로 자동 전환되고, 해당 내용이 resolve된 이우에야 다음으로 진행
      : 즉, Promise의 then과 흡사한 효과를 얻을 수 있음
     var addCoffee = function (name) {
        return new Promise(function (resolve) {
           setTimeout(function() {
             resolve(name);
           }, 500);
        });
     };
    
     var coffeeMaker = async function () {
       var coffeList = '';
       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();
profile
프론트엔드 개발자

0개의 댓글