자바스크립트의 비동기 처리를 살펴보면 다음과 같다.
비동기 흐름을 예측하기 어렵다.
// #1
console.log('Hello');
// #2
setTimeout(function() {
console.log('Bye');
}, 3000);
// #3
console.log('Hello Again');
// 'Hello'
// 'Hello Again'
// 3초 뒤에
// 'Bye'
의도치 않게 동작한다.
function getData() {
var tableData;
$.get('https://domain.com/products/1', function(response) {
tableData = response;
});
return tableData;
}
console.log(getData()); // undefined
자바스크립트는 비동기 처리가 필수적이지만 이러한 불특정 흐름은 통제되야 한다. 이를 위해 3가지 방법을 사용할 수 있다.
Callback
callback 함수를 이용해 비동기 흐름을 조절할 수 있다.
function getData(callbackFunc) {
$.get('https://domain.com/products/1', function(response) {
callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
});
}
getData(function(tableData) {
console.log(tableData); // $.get()의 response 값이 tableData에 전달됨
});
하지만 함수가 언제 끝날지 예측할 수 없기 때문에, 모든 종속 함수를 중첩시켜야 한다. 이를 콜백 지옥이라 한다.
$.get('url', function(response) {
parseValue(response, function(id) {
auth(id, function(result) {
display(result, function(text) {
console.log(text);
});
});
});
});
이러한 콜백 지옥은 코딩 패턴으로 해결 가능하지만 Promise나 Async를 이용해 더 편하게 구현할 수 있다.
// 코딩 패턴으로 극복
function parseValueDone(id) {
auth(id, authDone);
}
function authDone(result) {
display(result, displayDone);
}
function displayDone(text) {
console.log(text);
}
$.get('url', function(response) {
parseValue(response, parseValueDone);
});
Promise
Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타낸다.
Promise는 Callback 함수를 인자로 받고, 상태([[PromiseStatus]])와 값([[PromiseValue]])를 포함하는 객체입니다.
Promise Callback
Promise Callback은 2가지 인자를 받는데 첫번째 인자는 resolve 메소드로 Promise 객체의 콜백함수가 제대로 수행(fulfilled) 되었을 때 호출되는 메소드입니다. 두번째 인자는 reject 인자로 콜백함수가 거부(rejected) 되었을 때 호출됩니다.
new Promise((resolve, rejected) => {
if ('에러가 날 경우') {
rejected(err)
} else {
// 데이터를 받을 경우
resolve(data)
}
})
Promise Status
- Pending(대기)
- Fulfilled(이행)
- Rejected(실패)
Error 처리
- then()의 콜백함수의 두번째 파라미터로 처리 => then() 내부에서 일어나는 에러를 처리할 수 없다.
- catch()를 사용한 처리
// then()의 두 번째 인자로는 감지하지 못하는 오류
function getData() {
return new Promise(function(resolve, reject) {
resolve('hi');
});
}
getData().then(function(result) {
console.log(result);
throw new Error("Error in then()"); // Uncaught (in promise) Error: Error in then()
}, function(err) {
console.log('then error : ', err);
});
// catch()로 오류를 감지하는 코드
function getData() {
return new Promise(function(resolve, reject) {
resolve('hi');
});
}
getData().then(function(result) {
console.log(result); // hi
throw new Error("Error in then()");
}).catch(function(err) {
console.log('then error : ', err); // then error : Error: Error in then()
});
즉, catch()를 사용하는 것이 더 유리하다.
async & await
기본 문법
async function 함수명() {
await 비동기_처리_메서드_명();
}
비동기 처리 방식인 콜백 함수와 프로미스의 단점을 보완하고 개발자가 읽기 좋은 코드를 작성할 수 있다.
// 일반 프로미스
function runPromise() {
resetTitle();
playVideo();
sleep(1000).then(() => {
pauseVideo();
displayTitle();
})
.then(sleep.bind(null, 500))
.then(highlightTitle)
.then(sleep.bind(null, 2000))
.then(resetTitle)
}
// async/await 프로미스
async function runAsync() {
resetTitle();
playVideo();
await sleep(1000);
pauseVideo();
displayTitle();
await sleep(500);
highlightTitle();
await sleep(2000);
resetTitle();
}
예외 처리 => try, catch문 사용
async function logTodoTitle() {
try {
var user = await fetchUser();
if (user.id === 1) {
var todo = await fetchTodo();
console.log(todo.title); // delectus aut autem
}
} catch (error) {
console.log(error);
}
}
'프로그래밍 공부 > Javascript' 카테고리의 다른 글
var, let, const의 차이점과 호이스팅(Hoisting) (0) | 2022.02.09 |
---|---|
[자바스크립트] 이벤트 리스너 사용 시 this 바인딩 문제 (0) | 2021.11.19 |
[JS/Node] 자바스크립트 비동기 / TIL 26 ~ 27일차 (0) | 2021.10.14 |
객체 지향 프로그래밍: 클래스와 프로토타입 / TIL 21일차 (0) | 2021.10.05 |
submit 이벤트와 preventDefault (0) | 2021.10.03 |