자바스크립트에서 비동기를 처리할 때 사용되는 Callback과 Promise의 차이를 알아보자!
생각보다 많이 물어보는 프론트엔드 면접 질문 문제이다.
일단 결론 부터 듣고 시작하자!
callback을 사용하면 비동기 로직의 결과값을 처리하기 위해서는 callback안에서만 처리를 해야하고, 콜백 밖에서는 비동기에서 온 값을 알 수가 없습니다. 하지만 promise를 사용하면 비동기에에서 온 값이 promise 객체에 저장되기 때문에 코드 작성이 용이해집니다.
한마디로 비동기 처리 결과값을 사용여부가 차이점이다. Promise는 비동기 처리 결과값을 사용 가능하구, Callback은 이를 사용하지 못한다.
CallBack 비동기처리 방식
콜백 함수는 말 그대로 나중에 호출할 함수를 의미한다.
function async(callback) {
setTimeout(() => {
callback("waited 1 sec.");
}, 1000);
}
async(function (msg) {
console.log(msg);
});
자바스크립트에는 setTimeout() 이라는 대표적인 내장 비동기 함수가 있다.
setTimeout() 함수는 두번째 인자로 들어온 시간만큼 기다린 후에 첫 번째 인자로 들어온 콜백 함수를 실행한다.
따라서 위 코드를 실행하면 1초 뒤에 "waited 1 sec."이 콘솔에 찍힌다.
이렇게 어떠한 비동기 로직이 완료되었을 때 callback 함수를 실행시킴으로써 callback에서 작성한 어떠한 행동을 실행할 수 있게 된다.
그러나, 콜백함수의 단점으로는 비동기 로직의 처리 결과값을 콜백 함수 안에서만 처리해야 하구 이로 인해서 콜백 지옥에 빠질수 있다.
그러면 가독성도 떨어지고 에러처리가 힘들다.
Promise 비동기처리 방식
Promise란 비동기 작업이 종료된 후
1. 실행이 성공했는지?
2. 실행이 실패했는지?
3. 그럼 성공/실패의 결과 값이 무엇인지?
위 세가지의 내용을 미래(비동기 작업이 종료된 후)에 반환해주겠다고 약속하는 객체이다!
function async(key) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (key === true) resolve("waited 1 sec.");
else reject(new Error("Error!"))
}, 1000);
})
}
async(true)
.then((result) => { console.log(result); })
.catch((error) => { console.log(error); });
Promise를 사용하면 resolve는 성공했을 때, reject는 에러가 발생했을 때 첫 번째 인자로 어떠한 값을 넘길 수 있다.
async 함수에 true를 넣어 실행하면 1초 후,resolve의 "waited 1 sec."이 .then의 첫 번째 인자로 전달되어 "waited 1 sec."이 콘솔에 찍히고, false를 넣어 실행하면 1초 후, reject의 new Error("Error!")가 .catch의 첫 번째 인자로 전달되어 "Error: Error! at ..."가 콘솔에 찍힌다.
Promise 객체는 반드시 아래 3가지 상태중 한가지 상태를 갖는다.
대기(pending): 이행하거나 거부되지 않은 초기 상태, 즉 약속된 결과 값이 반환되지 않은 상태
이행(fulfilled): 연산이 성공적으로 완료된 상태.
거부(rejected): 연산이 실패한 상태
근데 여기서 Promise도 then, catch메서드 의 반환값은 또 다른 promise를 객체를 반환해서, Promise chaning이 발생 할 수 있다!
async / await
위의 Promise chaning의 대체제로 나온게 async / await이다. 꼬리 질문으로 이것도 많이 나온다.
함수 앞에 async를 붙이면, return 값으로 비동기 처리 결과값을 반환하는데, 비동기 처리 결과값인 promise 앞에 await를 붙여 주면,
함수안에 처리가 동기적 코드처럼 작성이 가능하고, 이걸 try , catch 형태로 에러 처리 한다면 위의 문제를 해결 할 수 있다.
ES8 추가로 도입된 async functions 그리고 await 키워드는
Promise 결과 값을 then, catch를 통해 다루는 것이 아닌 변수의 담아 동기적 코드처럼 작성해줄 수 있다는 점에서 편리함을 제공한다.
async function foo() {
const result = await promise(); // 프라미스가 이행될 때까지 아래 코드로 넘어가지 않음..
const resultTwo = await promiseTwo(); // 위 코드의 프로미스가 반환될 때까지 대기...
console.log(resultTwo); // 완료 되면 하단의 코드가 이어서 실행됨
const parellOne = promise(); // 위 아래 타이머는 동시에 시작됨.
const parelltwo = promiseTwo(); // 해당 프로미스 이행 값이 먼저 반환됨.(약 1초)
console.log(await parellOne);
console.log(await parelltwo); // 먼저 프로미스 객체가 반환되었지만 위 함수가 먼저 실행되어야 실행됨.
}
foo(); // 콘솔에 찍히는 값은 순서대로 1 2 3 "one" 3 "two" "one"
'개발 파운데이션 > JavaScript' 카테고리의 다른 글
Javascript 호이스팅 (0) | 2023.05.12 |
---|---|
자바스크립트 동작원리란? (0) | 2023.05.11 |
Javascript에서의 this란? (0) | 2023.05.10 |
클로저(closure)의 개념 (0) | 2023.05.09 |
프로토타입과 프로토 타입 체인은 알자! (0) | 2023.05.08 |