동기와 비동기?
(Thread) 작업1 → 작업2 → 작업3
위와 같은 작업이 있을 때 순서대로 작업이 처리되는 것을 동기라고 하며 앞의 작업이 진행 중일 때는 뒤의 작업을 수행할 수 없다.
JavaScript에서 기본적으로 동작하는 것은 동기이다. 이는 직관적이고 순차적이기 때문에 코드의 이해와 디버깅이 상대적으로 쉽다.
하지만, 앞 작업이 길어질 경우 뒷 작업도 늦어지기 때문에 브라우저나 앱의 응답 시간이 길어지는 단점이 있다.
이를 해결하기 위해 JavaScript에는 비동기 패턴을 제공한다. 비동기 패턴은 콜백함수, Promise, async/await 등을 사용하여 처리하며 작업이 완료되면 특정 콜백함수를 전달한다면 해당 작업이 끝났음을 알 수 있다. 비동기 패턴을 이용하면 시간이 오래 걸리는 작업이 진행되는 동안 다른 작업을 수행할 수 있다. JavaScript에서는 주로 이를 이용하여 네트워크 요청, 파일 업로드, 타이머 등과 같은 작업을 처리한다.
function firstTask() {
setTimeout(() => {
console.log("첫 번째 작업");
}, 2000);
}
// setTimeout : 비동기 함수(실행할 코드, 시간) * 시간은 1000 = 1초
function secondTask() {
console.log("두 번째 작업");
}
firstTask();
secondTask();
콜백 함수 사용
function fristTask(a, callback) {
setTimeout(() => {
const result = a + "첫 번째 작업";
callback(result);
}, 4000);
}
function secondTask(a, callback) {
setTimeout(() => {
const result = a + "두 번째 작업";
callback(result);
}, 3000);
}
function thirdTask(a, callback) {
setTimeout(() => {
const result = a + "세 번째 작업";
callback(result);
}, 2000);
}
console.log("코드 시작");
fristTask("1. ", (result) => {
console.log(result);
});
secondTask("2. ", (result) => {
console.log(result);
});
thirdTask("3. ", (result) => {
console.log(result);
});
Promise
JavaScript에서 비동기 작업을 처리하기 위한 내장 객체로 , 비동기 작업의 성공 또는 실패를 나타내고 그 결과값을 나중에 받을 수 있는 방법을 제공한다.
Promise 객체의 상태
1. 대기(Pending): 초기상태, 비동기 작업의 완료 또는 실패를 대기한다.
2. 이행(Fulfilled): 비동기 작업 성공. Promise 객체는 완료된 값으로 이행된다.
3. 거부(Reject): 비동기 작업 실패. Promise 객체는 실패한 이유를 나타내는 오류로 거부된다.
Promise 객체 상태변화 처리를 위한 메서드
1. then(이행callback, 거부callback): Promise 객체가 이행됐을 때와 거부됐을 때 호출되는 콜백함수 등록
2. catch(거부callback): Promise 객체가 거부됐을 떄 호출되는 콜백함수 등록
3. finally(항상호출되는callback): Promise 객체가 이행되거나 거부된 후에 호출되는 콜백함수 등록.
const promiseEx = new Promise((success, reject) => {
// 상수 promiseEx를 선언하고 생성자 함수 new Promise()를 호출하여 Promise 객체 생성
// Promise 객체 안에 완료되었을 때 콜백함수(success), 거부되었을 때 콜백함수(reject) 전달
// 비동기 작업 수행
const isSuccess = false; // 비동기 작업 결과
if (isSuccess) {
success("success 콜백함수 호출"); // 작업이 성공했을 경우 resolve 호출
} else {
reject("reject 콜백함수 호출"); // 작업이 실패했을 경우 reject 호출
}
});
promiseEx
.then((result) => {
console.log("Promise 성공:", result);
})
.catch((error) => {
console.log("Promise 실패:", error);
})
.finally(() => {
console.log("...Promise 완료");
});
async & await
JavaScript에서 비동기 코드를 보다 간결하고 동기적으로 작성할 수 있게 해주는 문법적 요소
1. async
- async 키워드를 사용하여 함수를 정의하면 해당 함수는 비동기 함수로 선언된다.
- async 함수 안에는 await 키워드를 사용하여 비동기 작업의 결과를 기다릴 수 있다.
- 항상 Promise를 반환하며 내부에 명시적으로 return문을 사용하여 값을 반환하면 해당 값으로 이행된 Promise가 반환된다.
2. await
- await 키워드는 async 함수 내에서만 사용할 수 있으며 Promise가 이행될 때(비동기 작업이 완료될 때)까지 함수의 실행이 일시중단.
- 오직 Promise 객체 앞에만 사용할 수 있으며 해당 Promise가 이행되면 그 결과를 반환한다.
function taskA(a, b, callback) {
setTimeout(() => {
const res = a + b;
callback(res);
}, 3000);
}
function taskB(a, b, callback) {
setTimeout(() => {
const res = (a + b) * -1;
callback(res);
}, 1000);
}
function runTasks() {
try {
const resultA = taskA(10, 10, (res) => {
console.log("resultA: ", resultA);
});
const resultB = taskB(10, 10, (res) => {
console.log("resultB: ", resultB);
});
} catch (error) {
console.error(error);
}
}
runTasks();
마지막 줄의 runTasks() 함수를 실행한 시점엔 taskA와 taskB가 완료되지 않았기 때문에(setTimeout) 결과가 모두 undefined가 된다.
이를 해결하기 위해 async와 await를 사용하는 것이다.
function taskA(a, b) {
return new Promise((success) => {
setTimeout(() => {
const res = a + b;
success(res);
}, 3000);
});
}
function taskB(a, b) {
return new Promise((success) => {
setTimeout(() => {
const res = (a + b) * -1;
success(res);
}, 1000);
});
}
async function runTasks() {
try {
const resultA = await taskA(10, 10);
console.log("resultA: ", resultA);
const resultB = await taskB(10, 10);
console.log("resultB: ", resultB);
} catch (error) {
console.error(error);
}
}
runTasks();
taskB의 setTimeout이 1초이고 taskA가 3초로 taskB가 먼저 수행이 되는 데도 결과는 A->B 로 나오는 이유는 await는 비동기 작업이 완료될 때까지 다음작업이 수행되지 않기 때문이다.
'JS > JavaScript' 카테고리의 다른 글
19. Truthy와 Falsy, 삼항연산자, 단락회로 평가, 조건문 응용 (1) | 2023.05.19 |
---|---|
18. 콜백함수 (0) | 2023.05.18 |
17. 배열 내장 함수 (0) | 2023.05.18 |
16. 기본, 참조 자료형 / 배열 함수 map() (0) | 2023.03.25 |
15. Spread & Rest Operator / Destructuring (0) | 2023.03.25 |