TIL 55 day 4장 콜백함수

Winney·2021년 1월 5일
0

코어자바스크립트

목록 보기
4/6
post-thumbnail

Callback Function

  • 다른 코드의 인자로 넘겨주는 함수
  • 제어권과 관련

    콜백함수란
    다른코드(함수 또는 메서드)에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수

var count = 0;
var cbFunc = function(){
  console.log(count);
  if (++count > 4) clearInterval(timer);
};
var timer = setInterval(cbFunc, 300);

// 결과 (0.3초마다)
0
1
2
3
4

cbFunc(); => 호출주체 : 사용자, 제어권: 사용자
setInterval(cbFunc, 300); => 호출주체: setInterval, 제어권 : setInterval

  • 콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수 호출 시점에 대한 제어권을 가진다.

this

Array.prototype.map = function(callback, thisArg) {
  var mappedArr = [];
  for(var i = 0; i <this.length; i++) {
    var mappedValue = callback.call(thisArg || window, this[i], i, this);
    mappedArr[i] = mappedValue;
  }
  return mappedArr;
}
  • call/apply 메서드 => thisArg 값이 있으면 해당 값을, 아니면 전역객체 지정

콜백함수는 함수다

  • 콜백 함수로 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출
var obj = {
  vals : [1,2,3],
  logValues: function(v, i) {
    console.log(this,v,i);
  }
};
obj.logValues(1,2);
[4, 5, 6].forEach(obj.logValues);

// 결과
{vals: Array(3), logValues: ƒ} 1 2
Window {...} 4 0
Window {...} 5 1
Window {...} 6 2
  • 콜백 함수 자리에 메소드를 넣었지만 일반 함수로 호출되어 전역객체를 바라보고 있다.

콜백 함수 내부의 this 바인딩

변수에 할당해서 사용하는 법

  • 전통적인 방법으로는 this를 변수에 할당해서 사용
  • 객체 내의 함수를 재활용 하는 방법
var obj1 = {
        name: 'obj1',
        func: function () {
            var self = this;
            return function() {
                console.log(self.name);
            };
        }
};
    
var callback = obj1.func();
setTimeout(callback, 1000); // obj1

var obj2 = {
        name: 'obj2',
        func: obj1.func
};
var callback2 = obj2.func();
setTimeout(callback2, 1500); // obj2

var obj3 = { name: 'obj3'};
var callback3 = obj1.func.call(obj3);
setTimeout(callback3, 2000); //obj3

=> func의 재사용을 위해 콜백으로 사용 할 메소드를 변수 할당해서 사용,
변수 할당을 하며 this를 지정해주는 방식

bind 메서드 활용법

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

var obj2 = {name: 'obj2'};
setTimeout(obj1.func.bind(obj2), 1500); // obj2
  • bind 메서드를 이용해 직접 this 지정

콜백 지옥과 비동기 제어

  • 콜백지옥(callback hell) : 콜백함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들정도로 깊어지는 현상
  • 비동기 : 동기의 반대말, 비동기적인 코드는 현재 실행중인 코드의 완료 여부와 상관없이 다음 코드를 실행
  • 동기 : 동기적인 코드는 현재 실행 중인 코드가 완료된 후 다음 코드를 실행, 즉시처리 가능한 대부분의 코드는 동기적
  • 별도의 요청, 실행대기, 보류 등과 관련된 코드는 비동기적

1) 비동기 작업의 동기적 표현 Promise

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('카페라떼'));
  • 2, 3번째 줄에서 클로저 등장(변수 prevName과 name 사용)

2) 비동기 작업의 동기적 표현 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 메서드 호출 시 Generator 함수 내에 가장 먼저 나타나는 yield해서 함수 실행 멈춤
  • 이후 다시 next 메서드 호출 시 앞서 멈췄던 부분부터 시작 다음 yield에서 멈춤

비동기 작업의 동기적 표현 Promis + 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된 이후 다음 진행
profile
프론트엔드 엔지니어

0개의 댓글