[js] 자바스크립트의 일급함수의 성질에 기반한 콜백함수의 비동기 처리 및 Promise, async / await
자바스크립트의 특이한 일급함수로써의 성질
🐀 함수가 변수처럼 할당될 수 있다
값처럼 사용할 수 있는 객체를 *일급객체라 한다.
자바스크립트의 함수는 호출가능한 객체로써, 피연산자로 사용될 때 함수 리터럴(값)로 해석된다.
즉, 하나의 값처럼 동작하는 함수를 다른 함수의 인자(args)로써 전달할 수 있고, 이를 파라미터로 받을 수 있다.
단, 함수는 호출되기 이전에, 함수 코드블록의 어떤 것도 실행되지 않는다.
함수 정의 방식
🐙 함수 정의 방식
- 함수 선언문
- 선언문이기 때문에 함수 호이스팅이 일어난다.
- 함수이름과 동일한 이름의 식별자가 생성, 함수 객체가 할당
1 2 3
function add(x, y) { return x + y; }
- 함수 표현식
- 함수 리터럴로 생성함 함수 객체가 변수에 할당
1 2 3
let add = function (x, y) { return x + y; };
Function 생성자 함수
1
let add = new Function("x", "y", "return x + y");
- 화살표 함수
- ECMAScript6 반복되는 표현들 때문에 간소화된 문법
1
let add = (x, y) => x + y;
- 축약문법
- 코드블록 안에 return문만 있을 때, 중괄호 및 return 예약어 제거 가능
1
const sum = () => 10 + 20;
- 파라미터가 하나인 경우, 괄호제거 가능
1 2 3 4
const logNum = (num) => { console.log(num); return num; };
- 코드블록 안에 return문만 있을 때, 중괄호 및 return 예약어 제거 가능
- 즉시 실행 함수
- 그룹 연산자
()
로 감싸면 함수 리터럴로 평가되어 함수 객체를 생성
1 2 3 4 5
(function () { let a = 3; let b = 5; return a + b; })();
콜백함수
🐁 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백함수라 한다
※ 인수로 함수를 받는 함수를 고차함수라 한다.
🐝 콜백함수를 이용한 비동기 처리.js
1
2
3
setTimeout(function () {
console.log("1초 경과");
}, 1000);
🐝 콜백함수를 이용한 배열 고차함수.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let res = [1, 2, 3].map(function (item) {
return item * 2;
});
console.log(res); // [2, 4, 6]
res = [1, 2, 3].filter(function () {
return item % 2;
});
console.log(res); // [1, 3]
res = [1, 2, 3].reduce(function (acc, cur) {
return acc + cur;
});
console.log(res); // 6
비동기 처리
🐁 특정 로직의 실행이 끝날 때까지 기다리지 않고, 다음 코드를 실행하는 처리 방식을 비동기 처리라 한다
요청을 하고 데이터를 받아올 때까지 기다려주는 코드가 없으면,
데이터를 다 받아오기도 전에 다음 코드가 실행되어 원하는 값을 얻을 수 없다.
1
2
3
4
5
6
7
8
9
10
function fetchMenu() {
setTimeout(() => {
let data = { firstMenu: "구독" };
return data;
});
}
let menu = fetchMenu();
console.log("menu", menu); //menu undefined
콜백함수를 사용하면 특정 로직이 끝났을 때, 원하는 동작을 실행시킬 수 있다.
즉, 일급함수의 성질을 이용해 함수를 파라미터로 전달하고, 전달된 함수를 호출할 수 있다.
🐝 callback.js
1
2
3
4
5
6
7
8
9
10
11
12
13
function fetchMenu(callback) {
setTimeout(() => {
let data = { firstMenu: "구독" };
callback(data);
}, 5000);
}
let menu;
fetchMenu(function (result) {
console.log("5초뒤 실행", result);
menu = result;
console.log("menu", menu);
});
콜백함수를 연속해서 사용할 때, 가독성이 떨어진다.
또한, 매번 에러처리를 위한 인자를 추가해야하며, 분기해야 한다.
결과를 나타낸다는 약속, Promise
🌋 Promise는 JavaScript 비동기 처리에 사용되는 객체다
연속된 콜백함수 사용으로 인해 낮아지는 가독성 문제를 해결할 수 있다.
📕 Promise 상태
- Pending(대기상태): 비동기 처리 로직이 아직 완료되지 않은 상태
- Fulfilled(이행상태): 비동기 처리가 완료되어 Promise가 결과값을 반환해준 상태
⚠️ 콜백함수의 인자 resolve를 호출하면 Fufilled 상태가 된다.
⚠️ Fulfilled 상태가 되면 then()을 이용하여 처리 결과값을 받을 수 있다.
- Rejected(실패상태): 비동기 처리가 실패하거나 오류가 발생한 상태
⚠️ 콜백함수의 인자 reject를 호출하면 Rejected 상태가 된다.
⚠️ Rejected 상태가 되면 error를 catch()로 받을 수 있다.
- Pending(대기상태): 비동기 처리 로직이 아직 완료되지 않은 상태
- Fulfilled(이행상태): 비동기 처리가 완료되어 Promise가 결과값을 반환해준 상태
⚠️ 콜백함수의 인자 resolve를 호출하면 Fufilled 상태가 된다.
⚠️ Fulfilled 상태가 되면 then()을 이용하여 처리 결과값을 받을 수 있다.
- Rejected(실패상태): 비동기 처리가 실패하거나 오류가 발생한 상태
⚠️ 콜백함수의 인자 reject를 호출하면 Rejected 상태가 된다.
⚠️ Rejected 상태가 되면 error를 catch()로 받을 수 있다.
🐝 promise.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function fetchMenu() {
return new Promise(function (resolve, reject) {
setTimeout(() => {
let data = { firstMenu: "구독" };
if (error) {
reject(new Error("Request is failed"));
}
resolve(data);
}, 5000);
});
}
let menu;
fetchMenu()
.then(function (result) {
console.log("5초 뒤 실행", result);
menu = result;
console.log("menu", menu);
})
.catch(function (error) {
console.log("에러 처리");
return;
});
- 🍪 체이닝 - 여러 개의 Promise를 연결하여 사용할 수 있다.
- then() 메서드를 호출하고 나면 새로운 Promise객체가 반환된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(1);
}, 1000);
})
.then(function (result) {
console.log(result); //1
return result + 10;
})
.then(function (result) {
console.log(result); //11
return result + 20;
})
.then(function (result) {
console.log(result); //31
});
- ☄️ Promise 2가지 에러 처리
- (1) then() 메서드의 두번째 인자
(2) catch() 권고
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function getData() {
return new Promise(function (resolve, reject) {
resolve("hi");
});
}
getData().then(
function (result) {
console.log(result);
throw new Error("Error in then()"); // 여기서 오류가 나는 경우
},
function (err) {
// 오류를 잡아내지 못한다
console.log("then error= ", err);
}
);
개발자가 읽기 좋은 비동기 처리 코드, async / await
🍝 해당 문법도 내부적으로는 Promise를 사용한다
🐝 async_await.js
1
2
3
4
5
6
7
8
9
10
11
12
async function init() {
try {
let menu;
menu = await fetchMenu();
await renderPageUI(); // 체이닝
console.log("menu", menu);
} catch (error) {
console.log("에러처리");
}
}
init();
Promise를 반환하는 함수 앞에 await를 붙여주면 마치 동기 처리를 구현하는 것처럼, 비동기 처리를 구현할 수 있다.
해당 문법의 예외처리는 자바스크립트의 기존 try / catch 문법을 이용하면 된다.
This post is licensed under CC BY 4.0 by the author.