JavaScript(9) - callback
JavaScript 관련 포스팅
- JavaScript(1) - async vs. defer
- JavaScript(2) - variable
- JavaScript(3) - operator
- JavaScript(4) - function
- JavaScript(5) - class vs. object
- JavaScript(6) - object
- JavaScript(7) - array
- JavaScript(8) - JSON
- JavaScript(9) - callback
- JavaScript(10) - promise
- JavaScript(11) - Regular expressions
- JavaScript(12) - Prototype과 Class 피하기
- JavaScript(13) - localStorage
Synchronous vs. Asynchronous
Synchronous(동기적)
- JavaScript는 synchronous(동기적)
- hoisting이 된 이후부터, 코드 작성 순서에 맞추어 동기적으로 실행됨
- hoisting이란?
var
,function declararion
은 선언 지점과 상관 없이 JS engine에 의해 문서의 최상단으로 끌어올려짐
console.log('1'); console.log('2'); console.log('3');
Console
1
2
3
Asynchronous (비동기적)
- 언제 코드가 실행될 지 예측 불가
e.g.)setTimeout()
: 지정한 시간이 지나면 전달한 callback fn을 호출함function setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number
console.log('1'); setTimeout(function() { console.log('2'); }, 1000); console.log('3');
코드를 순차적으로 읽어감
→
console.log(’1’);
실행
→setTimeout()
을 만나 1000ms(=1sec) 뒤 callback fn 실행 요청
→console.log(’3’)
실행
→ 1초 뒤console.log(’2’)
실행
(tip) 위의 callback fn는 arrow fn으로 바꿔 쓸 수 있음
console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');
Callback fn
- 나중에 다시(back) 부르는(call) 함수
- synchronous와 asynchronous 두 가지가 존재함
Synchronous callback
function printImmediately(print) {
print();
}
printImmediately(() => console.log('hello'));
Asynchronous callback
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'), 2000);
Result
console.log('1');
setTimeout(() => console.log('2'), 1000);
console.log('3');
// Synchronous callback
function printImmediately(print) {
print();
}
printImmediately(() => console.log('hello'));
// Asynchronous callback
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(()=> console.log('async callback'), 2000);
-
코드 실행순으로 코드 나열을 다시 해보면,
function printImmediately(print) { // hoisting print(); } function printWithDelay(print, timeout) { // hoisting setTimeout(print, timeout); } console.log('1'); // 동기 setTimeout(() => console.log('2'), 1000); // 비동기 console.log('3'); // 동기 printImmediately(() => console.log('hello')); // 동기 printWithDelay(()=> console.log('async callback'), 2000); // 비동기
function declaration은 hoist되므로 코드 최상단으로 끌어올려짐
function printImmediately
와function printWithDelay
가 상단으로 이동
이후 코드들을 순서대로 실행함
‘1 → 3 → hello → 2 → async callback’ 순으로 console이 찍힘
Callback hell example
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if((id === 'minji' && password === 'pass') ||
(id === 'someone' && password === 'pass too')
) {
onSuccess(id);
} else {
onError(new Error('not found'));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if(user === 'minji') {
onSuccess({ name: 'minji', role: 'admin' });
} else {
onError(new Error('no access'));
}
}, 1000);
}
}
- 사용자에게
id
와password
를 입력 받음 - 서버에 login
- login이 성공적이라면 해당 id를 받아와 role 요청
- role을 성공적으로 받아오면
name
과role
이 있는 사용자의 object를 출력
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
id,
password,
user => {
userStorage.getRoles(
user,
userWithRole => {
alert(`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
},
error => {
console.log(error);
}
);
},
error => {console.log(error)});
문제점
- 가독성이 떨어짐
- error, debugging, 유지 보수가 어려움
< 출처 >
“자바스크립트 11. 비동기 처리의 시작 콜백 이해하기, 콜백 지옥 체험 😱 JavaScript Callback | 프론트엔드 개발자 입문편 (JavaScript ES6),” 유튜브 비디오, 21:15, 게시자 “드림코딩 by 엘리,” 2020년 6월 9일, https://youtu.be/tJieVCgGzhs