자바스크립트에는 비동기적으로 실행되는 함수들이 있다. (ex. setTimeout, AJAX를 활용한 라이브러리 함수들)
비동기 함수들은 실행순서를 제어해주지 않으면 코드의 실행 순서를 예측할 수 없고 코드의 가독성도 떨어진다.
비동기 함수들의 실행 순서를 제어하는 방법에는 어떤 것이 있는지 알아봤다.
Callback
- 콜백함수는 다른 코드의 인자로 넘겨주는 함수로, 콜백 함수를 넘겨받은 코드는 이 콜백함수를 실행할 제어권을 가져 적절한 시점에 콜백 함수를 실행할 수 있게 된다.
- 콜백지옥
setTimeout(
function(name) {
var Teletubbies = name;
console.log(Teletubbies);
setTimeout(
function(name) {
Teletubbies += ', ' + name;
console.log(Teletubbies);
setTimeout(
function(name) {
Teletubbies += ', ' + name;
console.log(Teletubbies);
setTimeout(
function(name) {
Teletubbies += ', ' + name;
console.log(Teletubbies);
},
500,
'뽀'
);
},
500,
'나나'
);
},
500,
'뚜비'
);
},
500,
'보라돌이'
);
실행 결과
보라돌이
보라돌이, 뚜비
보라돌이, 뚜비, 나나
보라돌이, 뚜비, 나나, 뽀
콜백 지옥에 빠지지 않는 방법
- 각 스텝을 독립적인 함수로 만든다. 이전 스탭에서 error가 발생하지 않았을 경우 다음 단계의 함수를 실행하는 방식으로 코딩한다.
- 그런데 promise 라는 더 좋은 방법이 있음.
Promise
- Promise는 실행은 바로 하되, 결괏값은 나중에 받는 객체이다.
- Promise 객체를 만드는 방법
const promise = new Promise(function(resolve, reject) { ... } );
- 실제로는 변수에 할당하기 보다는 어떤 함수의 리턴값으로 바로 사용되는 경우가 많다.
function returnPromise() {
return new Promise((resolve, reject) => { ... } );
}
- Promise 객체 생성 후 resolve, reject를 매개변수로 갖는 콜백함수를 넣는다.
- resolve 또는 reject가 실행되기 전까지는 then이나 catch 구문으로 넘어가지 않는다.
- 따라서 비동기작업을 동기적으로 표현할 수 있다.
- new Promise의 실행결과는 then을 붙였을 때 받게 된다.
- then에서 다시 다른 then이나 catch를 붙일 수도 있다.
- 이전 then의 리턴 값은 다음 then의 매개변수로 넘어간다.
- Promise를 리턴하는 경우에는 프로미스가 수행된 후 다음 then이나 catch가 호출된다.
new Promise(function(resolve) {
setTimeout(function() {
var name = '보라돌이';
console.log(name);
resolve(name);
}, 500);
})
.then(function(prevName) {
return new Promise(function(resolve) {
setTimeout(function() {
var name = prevName + ', 뚜비';
console.log(name);
resolve(name);
}, 500);
});
})
.then(function(prevName) {
return new Promise(function(resolve) {
setTimeout(function() {
var name = prevName + ', 나나';
console.log(name);
resolve(name);
}, 500);
});
})
.then(function(prevName) {
return new Promise(function(resolve) {
setTimeout(function() {
var name = prevName + ', 뽀';
console.log(name);
resolve(name);
}, 500);
});
});
콜백 지옥 문제를 해결했음에도 Promise 가 갖고 있는 문제점
- 수많은 then과 catch 때문에 여전히 코드가 깔끔하지 않다.
- 여러개의 then 중 하나에서 오류가 발생하면 디버깅하기 어렵다.
- try catch 문을 사용할 수 없다. catch() 메서드만을 이용해 예외처리를 해야한다.
async / await
- async/await은 promise 를 더 쉽게 사용할 수 있는 방법이다.
- async는 비동기적으로 함수를 실행시킨다. 그리고 항상 Promise를 반환한다.
- 비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고,
- 함수내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 표기하면,
- 뒤의 내용은 자동으로 Promise로 전환되고, 해당 내용이 resolve 된 이후에야 다음으로 진행한다.
var addMember = function(name) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(name);
}, 500);
});
};
var television = async function() {
var Teletubbies = '';
var _addMember = async function(name) {
Teletubbies += (Teletubbies ? ',' : '') + (await addMember(name));
};
await _addMember('보라돌이');
console.log(Teletubbies);
await _addMember('뚜비');
console.log(Teletubbies);
await _addMember('나나');
console.log(Teletubbies);
await _addMember('뽀');
console.log(Teletubbies);
};
television();
+) axios.get(), fetch() 등의 함수는 API 호출 결과를 Promise로 리턴한다. 따라서 .then, .catch 메서드를 사용할 수 있다.
예시 코드 출처
- 코어자바스크립트 ch4. 콜백 함수
참고 링크
- https://www.daleseo.com/js-async-callback/
- https://www.daleseo.com/js-async-promise/
- https://www.daleseo.com/js-async-async-await/
- https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/
- https://joshua1988.github.io/web-development/javascript/promise-for-beginners/
- https://joshua1988.github.io/web-development/javascript/js-async-await/
'Language > JavaScript' 카테고리의 다른 글
[JS] 코어자바스크립트 ch6. 프로토타입 (0) | 2021.07.04 |
---|---|
[JS] 코어자바스크립트 ch3. this (0) | 2021.07.03 |
[JS] 화살표함수 (0) | 2021.07.02 |
[JS] 함수 선언문과 함수 표현식 (0) | 2021.05.28 |
[JS] 얕은 복사 깊은 복사 (0) | 2021.05.14 |