TIL15 l Callback Function

Noma·2021년 1월 22일
0

Callback Function

콜백 함수는 다른 함수에 인자로 전달되는 함수이며, 이는 다른 함수의 내부에서 호출되어 몇 가지의 루틴이나 동작을 완료한다.

  1. 다른 함수에 인자로 전달할 수도, 변수에 할당할 수도 있다.
  2. 동기적 콜백과 비동기 콜백으로 나눠진다.

1) Synchronous Callback

- Synchronous란?

Function hoisting 된 이후로 코드가 작성된 순서대로 순차적으로 실행되며, 이전 코드가 완료될 때까지 기다린 후 다음 코드가 실행되는 것을 말한다.

*hoisting이란? var, function 선언문이 자동적으로 제일 위로 올라가는 것을 말한다.

- Synchronous Callback 예시

function greeting(name) {
  console.log(`Hello, ${name}!`);
}

function UserInput(callback) {
  const name = prompt('Please enter your name.');
  callback(name);
}

UserInput(greeting);
console.log("I'm waiting...");
[console] - merry 입력시
Hello, merry!
I'm waiting...

2) Asynchronous Callback

- Asynchronous란?

" takes some time "
" happens in the future, not right now."

이전 코드의 실행을 기다리지 않고 다음 코드가 실행되는 것을 말합니다. 사이트 또는 앱의 응답성을 유지하며 사용자의 대기 시간을 줄입니다.

- Asynchronous Callback 예시

function printWithDelay(print,timeout){
    setTimeout(print,timeout);
}
printWithDelay(()=>console.log('async callback'),2000);
console.log("I'm not waiting!");
[console]
I'm not waiting!
async callback

특징

비동기 콜백은 Promise.then() 블록 내에서나 fetch()와 같은 최신 웹 API에서도 자주 사용된다.

3) Callback Hell

비동기식 프로그래밍 코드에서 볼 수 있는 안티패턴으로, "if" 문이나 함수를 다루기 어렵게 중첩된 것을 말한다.

- 문제점

➡ 가독성 떨어짐, 디버깅 어려움, 유지보수 어려움

- 예시 (from. Dream coding)

본래는 사용자가 로그인하면 백엔드에 로그인한 사용자와 관련된 정보들을 요청해 한번에 받아오는 것이 맞지만, 아래의 예시는 사용자의 아이디와 패스워드를 받은 후 사용자의 role은 따로 네트워트 요청해 다시 받아와야하는 그런 나쁜 백엔드라고 가정하고 시작합니다.

➡ 실제 백엔드가 없기때문에 setTimeout을 이용해 어느 정도 딜레이를 주면서 네트워크와 통신하는 것처럼 만들었습니다.

class UserStorage{
    loginUser(id,password,onSuccess,onError){
        setTimeout(()=>{
            if(
                (id==='ellie'&&password==='dream')||(id==='coder'&&password==='academy')
            ){
                onSuccess(id);
            }else{
                onError(new Error('not found'));
            }
        },2000);
    }
    getRoles(user,onSuccess,onError){
        setTimeout(()=>{
            if(user==='ellie'){
                onSuccess({name:'ellie',role:'admin'});
            }else{
                onError(new Error('no access'));
            }
        },1000);
    }
}
const userStorage=new UserStorage();
const id=prompt('enter your id');
const password=prompt('enter your password');
userStorage.loginUser(
    id,
    password,
    userID=>{
        userStorage.getRoles(
            userID,
            userWithRole=>alert(`Hello ${userWithRole.name}! You have a ${userWithRole.role} role.`),
            error=>console.log(error)
        );
    },
    error=>console.log(error)
);

4) How do I fix callback hell?

(1-2: 코드를 잘 읽히게 하는 방법, 3: 코드를 안정화시키는 방법)

1. Keep your code shallow

함수를 nesting 하지 말고, anonymous function 보다는 이름있는 함수를 사용하여 최대한 프로그램의 최상위 레벨에서 코드를 작성하자. 그러면,

  • 기능을 잘 설명하는 함수 이름 덕분에 코드를 쉽게 읽을 수 있다.
  • 예외 발생 시, "anonymous" 대신 실제 함수 이름을 참조하는 스택트레이스를 얻을 수 있다.
  • 이름을 가지고 함수를 이동시키거나 참조할 수 있게 된다.

2. Modularize

각자가 한가지 일을 하는 작은 모듈로 만들고, 그것들을 더 큰 일을 하는 다른 모듈로 조립하라!

재사용 가능한 함수를 만들어 모듈에 배치하여 코드를 이해하는 데 필요한 인지 부하를 줄여준다. 이렇게 코드를 작은 조각으로 나누면 오류 처리, 쓰기 테스트 작성, 안정적이고 문서화된 open API 생성, 리팩터링에도 도움이 된다.

3. Handle every single error

오류의 종류는 다양하다. 오류는 언제 어디서 나타날 지 모르기때문에 그에 대한 계획을 세워야한다.

  • 프로그래머에 의한 구문 오류(일반적으로 프로그램을 처음 실행하려고 할 때 잡히는)
  • 프로그래머에 의한 런타임 오류(코드는 실행되었지만 뭔가 엉망으로 만드는 버그)
  • 유효하지 않은 파일 권한, 하드 드라이브 장애, 네트워크 연결 없음 등에 의해 일어나는 플랫폼 에러...

4. Function hoisting

함수 선언문을 밑으로 이동시켜라!

hoisting이란? var, function 선언문이 자동적으로 제일 위로 올라가는 것을 말한다.

❗ 참고자료
http://callbackhell.com/
https://developer.mozilla.org/en-US/docs/Glossary/Callback_function
https://www.youtube.com/channel/UC_4u-bXaba7yrRz_6x6kb_w

profile
오히려 좋아

0개의 댓글