Core JS 04. callback

강지원·2022년 2월 3일
0

Core JS

목록 보기
4/5
post-thumbnail

콜백 함수

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

setInterval의 콜백 함수로 개념을 파악해보자.

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

코드를 실행하면 0.3초에 한 번씩 숫자가 0부터 1씩 증가하다 4가 출력된 이후 종료된다. cbFunc가 아닌 setInterval에 cbFunc 함수를 넘겼고, setInterval은 콜백 함수 호출 시점에 대한 제어권을 갖게 되었다.

= 함수가 주체적으로 실행되는 것이 아닌, 다른 함수에 의해 컨트롤된다.

인자

콜백 함수를 호출할 때 인자로 넘겨줄 값들 및 순서는 정해져있다.

this

콜백 함수도 함수이다.
기본적으로 this는 전역객체를 참조하지만,
제어권을 넘겨받을 코드에서 콜백 함수에
this가 될 대상을 지정한 경우 그 대상을 참조한다.

어떤 함수의 인자에 객체의 메서드 전달
콜백 함수로 어떤 함수의 인자에 객체의 메서드를 전달해도
그 메서드는 함수로서 호출.

var obj = {
  vals: [1, 2, 3],
  logvalues: function(v,i) {
    console.log(this, v, i);
  }
};
obj.logvalues(1, 2); //메서드로 호출할 경우 this는 obj.
[4, 5, 6].forEach(obj.logValues); //this는 전역객체
// logValues메서드를 forEach 함수의 콜백 함수로 전달.
// obj.logvalues가 가리키는 함수만 전달한 것임. 
// forEach에 의해 콜백이 함수로 호출된다.
콜백 함수 내부의 this에 다른 값 바인딩
위와 같이, 메서드를 콜백 함수로 전달하면 this는 전역객체를 바라본다. this가 객체를 바라보게 하고 싶다면 어떻게 해야할까? 전통적으로는 this를 다른 변수에 담아 콜백 함수로 활용했다. 이는 너무 번거롭고, 이를 보완하는 방식으로 ES5에서 등장한 bind 메서드를 이용할 수 있다.

Fxxking callback hell

setTimeout(function (name) {
  var subject = name;
  console.log(subject);
  
  setTimeout(function (name) {
  	subject += ',' + name;
  	console.log(subject);
    
    setTimeout(function (name) {
  		subject += ',' + name;
  		console.log(subject);
      
      	setTimeout(function (name) {
  			subject += ',' + name;
  			console.log(subject);
        }, 500, 'REDUX');
     }, 500, 'MOBX');
  }, 500, 'CONTEXT API');
}, 500, 'PROPS');

결과적으로는 'PROPS','CONTEXT API','MOBX','REDUX'가 출력되는
코드이지만 연속된 callback으로 인해 코드의 가독성이 떨어질 뿐 아니라
유지보수가 상당히 어려워진다.

Callback Hell Escape

1. 기명 함수 사용

함수 표현식으로 이해할 수 있다.

var subject = '';

var add1 = function(name) {
  subject = name;
  console.log(subject);
  setTimeout(add2, 500, 'MOBX')
};
var add2 = function(name) {
  subject += ',' + name;
  console.log(subject);
  setTimeout(add3, 500, 'CONTEXT API')
};
var add3 = function(name) {
  subject += ',' + name;
  console.log(subject);
  setTimeout(add4, 500, 'PROPS')
};
var add4 = function(name) {
  subject += ',' + name;
  console.log(subject);
};

setTimeout(add1, 500, 'REDUX')

Promise

callback을 쉽게 처리하기 위한 방법 중 하나

promise는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타낸다. 비동기 작업이 완료될 때 resolve/reject를 호출하는 방법으로 동기적 표현이 가능하며, 둘 중 하나가 실행되기 전까지는 다음 또는 오류 구문으로 넘어가지 않는다.

resolve : 주어진 값으로 이행하는 .then 반환
reject : 거부된 promise를 반환
then() : promise를 리턴하고 두 개의 콜백 함수를 인자로 받음(이행했을 때, 거부했을 때)

new Promise(function (resolve) {
  setTimeout(function () {
    var name = 'JS';
    console.log(name);
    resolve(name);
  }, 500);  
})
.then(function (prevName) {
  return new Promise(function (resolve) {
  	setTimeout(function () {
    	var name = 'REACT';
    	console.log(name);
    	resolve(name);
  	}, 500);
  });
})
.then(function (prevName) {
  return new Promise(function (resolve) {
  	setTimeout(function () {
    	var name = 'API';
    	console.log(name);
    	resolve(name);
  	}, 500);
  });
})
.then(function (prevName) {
  return new Promise(function (resolve) {
  	setTimeout(function () {
    	var name = 'Library';
    	console.log(name);
    	resolve(name);
  	}, 500);
  });
});

promise + Async/await

async : 비동기 작업을 수행하고자 하는 함수 앞에 표기
await : 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 표기
이 작업으로 뒤의 내용을 promise로 자동 전환할 수 있다.
즉, promise의 then과 유사한 효과를 얻을 수 있다.

// 비동기 처리될 함수 작성
var addSubject = function (name) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(name);
    }, 500);
  });
};

// async/await를 사용해 비동기 처리 함수를 담을 함수 작성 
var subjectMaker = async function () {
  var subjectList = '';
  var _subject = async function (name) {
    subjectList += (subjectList ? ',' : '') + await addSubject(name);
  };
  
  await _addSubject('HTML');
  console.log(gimbapList);
  await _addSubject('CSS');
  console.log(gimbapList);
  await _addSubject('JS');
  console.log(gimbapList);
  await _addSubject('REACT');
  console.log(subjectList);
};
subjectMaker();
profile
'Why' better than 'Yes'

0개의 댓글