콜백함수

파송송계란빡 ㅣ 2022. 3. 23. 02:34

콜백함수

정의

함수에 파라미터로 들어가는 함수가 콜백함수

용도

순차적으로 실행하고 싶을 때 씀

 

많이 사용하는 addEventListener에도 콜백 함수가 들어가있다.

함수의 파라미터 자리에 있는 바로 function 부분!!

버튼을 클릭 한 후에 function() 인 콜백 함수 부분 실행되므로 순차적임~

addEventListener("click", function() {
	
})

 

또한 setTimeout에도 콜백 함수가 들어가있다.

1초 경과 후에 function() { } 인 콜백함수가 실행된다.

setTimeout(function() {

}, 1000)

 

특징

1. 다른데스 만든 함수도 콜백함수로 넣을 수 있다.

function getName() {
	console.log("name");
}

document.querySelector(".button").addEventListener("click", getName);

 

2. 콜백 함수가 필요한 함수들에게만 콜백함수 사용 가능

addEventListener(), setTimeout() 등

 

 

예제1

first() 함수안의 코드 실행해주세요, 그런데 파라미터에 seconde() 집어넣어서요.
순차적으로 first()를 실행 한 후 파라미터로 받은 seconde() 함수 실행

 

예제2

자바스크립트를 통해서 DB에서 데이터를 뽑고싶다.

그런데 A뽑고

그 다음에 B뽑고

그 다음에 C뽑고

 

이렇게 하면 계속 코드가 우측으로 길어지고, 보기 복잡하다!

promise를 사용하면 조금 더 간단하게 바꿀 수 있다.

promise는 아래에서 다루도록 한다.

db.collection("post").findOne(A, function() {
    db.collection("post").findOne(A, function() {
        db.collection("post").findOne(A, function() {
    
        })
    })
})

 

 

예제3

setTimeout()을 이용해서 비동기 콜백 함수, 동기 콜백 함수 사용해보기

 

예제4

콜백 지옥 체험하기

//콜백 지옥 체험
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('not Found'));
            }
        }, 1000)
    }
}

//1. id, pass입력
//2. login 성공적으로 돤다면, id를 받아서
//3. 역할을 받아온다.
//4. 역할을 잘 받아온다면 사용자의 이름과, 역할 출력

const userStorage = new UserStorage();                  //UserStorage클래스를 통해서 객체 생성
const id = prompt("enter your id");                     // id는 입력받아옴
const password = prompt('enter your password');         // password는 입력받아옴

userStorage.loginUser(                                  //UserStorage클래스의 loginUser 메서드 사용
    id,
    password,
    user => {                                           //성공시 다시 UserStorage클래스의 getRoles 메서드 사용
        userStorage.getRoles(
            user,
            (userWithRole) => {                         //받아온 role을 통해 alert 수행
                alert(`hello ${userWithRole.name}, you have a ${userWithRole.role} role`)
            },
            (error) => {
                console.log(error)
            }
        )
    },
    error => {
        console.log(error)
    }
)

 


promise

정의

비동기 처리를 위한 콜백 함수의 단점을 극복하기 위해 사용

 

특징

1. new로 promise 객체를 생성

2. promise 객체에서는 executor라는 함수가 자동적으로 실행

3. exucutor 함수는 sesolve와 reject라는 두개의 함수를 인자로 받아서 비동기 처리 함수를 실행

4. executor를 통해 비동기 처리 함수를 실행 완료 후, 해당 작업이 성공하면 resolve, 실패하면 reject 함수 호출

//promise 객체 생성
const promise = new Promise((resolve, reject) => {
    console.log("doing someting");
    
    //비동기 작업 수행
    setTimeout(() => {
        resolve("ellie");       //성공하면 resolve에 "ellie"를 넘겨줌
    }, 2000);
});

 

Promise 객체의 3가지 상태

  • pending(대기) : 비동기 처리가 아직 실행되지 않은(초기) 상태
  • fulfilled(이행) : 비동기 처리가 성공적으로 완료된 상태
  • rejected(실패) : 비동기 처리가 실패한 상태

 

 

then 메서드를 이용해서 promise 받아보기

promise가 정상적으로 성공 후 마지막으로 resolve라는 콜백함수를 통해서 value로 값을 전달해줍니다.

promise.then((value) => {
    console.log(value)
})

 

실패시 reject 사용, 성공하든 실패하든 무조건 사용되는 finally 사용

//promise 객체 생성
const promise = new Promise((resolve, reject) => {
    console.log("doing someting");

    //비동기 작업 수행
    setTimeout(() => {
        reject(new Error("no network"));       //실패하면 reject Error 객체를 넘겨줌
    }, 2000);
});


//2. consumers : then, catch, finally
//then : promise가 정상적으로 성공하여서 마지막으로 resolve라는 콜백함수를 통해서 
//value로 값을 전달해줍니다.
promise
    .then((value) => {
        console.log(value)
    })
    .catch((error) => {
        console.log(error)
    })
    .finally(() => {
        console.log("성공하든 실패하든 무조건 실행됩니다!")
    })

 

예제1 .then 체이닝을 이용해서 성공시 계속적으로 다음 then으로 값 전달

//promise 체이닝
const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000)      //1초 있다가 숫자 1을 전달
});

fetchNumber
    .then(num => num * 2)                   //전달 받은 1을 *2함
    .then(num => num * 3)                   //위에서 성공한 숫자를 *3함
    .then(num => {                          //다시 promise를 통해서 1초 뒤에 -1 해줌
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(num - 1), 1000);
        });
    })
    .then(num => console.log(num));         //화면에 출력

 

예제2

.then 체이닝을 이용해서 성공시 계속적으로 다음 then으로 값 전달

.then에 받아온 값이 한개인 경우 생략 가능

const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve('🐔'), 1000);
    });


const getEgg = (hen) =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${hen} => 🥚`), 1000);
    });


const cook = (egg) =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => 🍳`), 1000);
    });

getHen()
    .then(getEgg)           // .then(hen => getEgg(hen))
    .then(cook)             // .then(egg => cook(egg))
    .then(console.log);     // .then(meal => console.log(meal));

 

예제3

만약 에러가 발생하여 getEgg를 받아오지 못하는 경우

catch를 이용해서 에러 처리

const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve('🐔'), 1000);
    });


const getEgg = (hen) =>
    new Promise((resolve, reject) => {
        setTimeout(() => reject(new Error(`error! ${hen} => 🥚`)), 1000);
    });


const cook = (egg) =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => 🍳`), 1000);
    });

getHen()
    .then(getEgg)           //위에서 오류 발생
    .catch(error => {       //계란이 없어서 계란을 받아올 수 없으면
        return '🥖'         //대신 빵 사용
    })
    .then(cook)
    .then(console.log)
    .catch(console.log)

 

예제4

콜백 지옥을 Promise 변경

//콜백 지옥 체험
class UserStorage {
    loginUser(id, password) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if ((id === "ellie" && password === "dream") || (id === "coder" && password === "academy")) {
                    resolve(id);
                } else {
                    reject(new Error('not Found'));
                }
            }, 2000)
        });
    }

    getRoles(user) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (user === "ellie") {
                    onSuccess({ name: "ellie", role: "admin" });
                } else {
                    onError(new Error('not Found'));
                }
            }, 1000);
        })
    }
}
//1. id, pass입력
//2. login 성공적으로 돤다면, id를 받아서
//3. 역할을 받아온다.
//4. 역할을 잘 받아온다면 사용자의 이름과, 역할 출력

const userStorage = new UserStorage();                  //UserStorage클래스를 통해서 객체 생성
const id = prompt("enter your id");                     // id는 입력받아옴
const password = prompt('enter your password');         // password는 입력받아옴

userStorage.loginUser(id, password)
    .then(userStorage.getRoles)
    .then(user => alert(`Hello ${user.name}, you have a ${user.role} role.`))
    .catch(console.log);
콜백함수