다른 함수의 인자로 들어가는 함수
콜백 함수를 인자로 받은 함수는 콜백 함수를 원하는 위치에서 원하는 시점에 호출할 수 있다.
콜백 함수의 인자의 순서가 정해져 있는 경우가 있다.
/* 1. forEach, map, filter, find, ... */
Array.map(
(function callback(currentElement, index, array) {...}), thisArg
);
// currentElement : 현재 처리하는/처리할 요소
// index : 현재 처리하는/처리할 요소의 인덱스
// array : 콜백 함수를 호출한 배열
// thisArg : 콜백 함수의 this 값
/* 2. reduce, reduceRight */
Array.reduce(
(function callback(accumulator, currentValue, currentIndex, array) {...}), initialValue
);
// accumulator : 콜백 함수의 반환값(콜백의 이전 반환값 or initialValue)
// currentValue : 처리할 현재 요소
// currentIndex : 처리할 현재 요소의 인덱스
// array : 콜백 함수를 호출한 배열
// initialValue: 콜백 함수에 제공할 첫 번째 값
따라서, 해당 함수에서는 콜백 함수의 인자의 위치를 고려하여 작성해야 한다.
// 정상
[10, 20, 30].forEach((currentValue, index) => {
console.log(`Index[${index}] = ${currentValue}`);
});
// 오류
[10, 20, 30].forEach((index, currentValue) => {
console.log(`Index[${index}] = ${currentValue}`);
});
정상 | 오류 |
---|---|
Index[0] = 10 | Index[10] = 0 |
Index[1] = 20 | Index[20] = 1 |
Index[2] = 30 | Index[30] = 2 |
콜백 함수는 함수다
콜백 함수가 객체의 메서드 형태로 존재하더라도, 호출할 땐 함수의 형태로 호출한다.const obj = { num: [1, 2, 3], printNum: function(v, i) { console.log(this, v, i); } }; obj.printNum("Value", "Index"); // { num: [ 1, 2, 3 ], printNum: [Function: printNum] } Value Index
콜백 함수의 기본 this 값은 콜백 함수를 호출하는 객체/함수
다.
콜백 함수의 this 값을 변경하려는 경우, bind 메서드
를 사용한다.
const obj2 = {
num: [4, 5, 6]
}
obj.printNum.bind(obj2)("Value", "Index");
// { num: [ 4, 5, 6 ] } Value Index
수많은 비동기 함수를 동기적(순차적)으로 수행하기 위해 콜백 함수를 중첩적으로 작성하여 가독성이 떨어지는 현상
// AS-IS (Callback Hell)
getData(function(a) {
getMoreData(function(b) {
getMoreData(function(c) {
getMoreData(function(d) {...});
});
});
});
비동기 연산을 수행하고 성공(Resolve) / 실패(Reject) 여부를 반환하는 객체
Promise 객체의 상태
- Pending(대기 중) : 비동기 연산이 아직 수행되지 않은 상태
- Fulfilled(수행 완료) : 비동기 연산이 성공적으로 수행되어 결과값을 반환한 상태
- Rejected(거부됨) : 비동기 연산이 실패하거나 오류가 발생한 상태
Promise.all vs Promise.allSettled
: 여러 개의 Promise를 병렬로 수행한 뒤 전체 결과를 배열 형태로 반환함
- 공통점
- 모든 Promise가 완료될 때까지 기다림
- 차이점
- Promise.all
- 모든 Promise가 Fulfilled인 경우에만 최종적으로 Fulfilled를 반환함
- 단 하나의 Promise가 Rejected면, 최종적으로 Rejected로 반환함
- Promise.allSettled
- 각 Promise의 Fulfilled/Rejected 결과를 배열 형태로 반환함
- Promise의 결과가 Fulfilled면 value를 반환하고, Rejected면 resaon을 반환함
- 최종 결과를 Fulfilled와 Rejected로 나누어 각각 처리함
// TO-BE (Promise)
function getFinalData() {
function getData() {
return new Promise(function(resolve) {
function(a) {
resolve(resultA);
}
});
}
function getMoreData(resultA) {
return new Promise(function(resolve) {
function(b) {
resolve(resultB);
}
});
}
function getMoreData(resultB) {
return new Promise(function(resolve) {
function(c) {
resolve(resultC);
}
});
}
function getMoreData(resultC) {
return new Promise(function(resolve) {
function(d) {
resolve(finalData);
}
});
}
}
// TO-BE (Promise ~ then)
function getData() {
return resultA;
}
function getFinalData() {
getData()
.then(function getMoreData(resultA) {
return resultB;
})
.then(function getMoreData(resultB) {
return resultC;
})
.then(function getMoreData(resultC) {
return finalData;
})
}
비동기 작업을 수행할 함수 앞에 async
키워드를 입력하고,
내부에서 동기적으로 수행할 함수의 앞에 await
키워드를 입력함
// TO-BE (async/await)
async function getFinalData() {
let resultA = await getData();
let resultB = await getMoreData(resultA);
let resultC = await getMoreData(resultB);
let finalData = await getMoreData(resultC);
}