반응형
비동기
비동기 프로그래밍은 코드가 다른 코드와 동시에 실행될 수 있도록 하여, 시간이 오래 걸리는 작업(예: 네트워크 요청, 파일 읽기/쓰기 등)을 비동기적으로 처리할 수 있게 합니다.
콜백 함수 (a.k.a 콜백 지옥)
- 순서를 보장하기 위해서 콜백 함수를 사용합니다.
function task1(callback) {
console.log("task1");
callback();
}
function task2(callback) {
setTimeout(() => {
console.log("task2");
callback();
}, 1000);
}
function task3(callback) {
console.log("task3");
callback();
}
function task4(callback) {
console.log("task4");
callback();
}
task1(() => {
task2(() => {
task3(() => {
task4(() => {
console.log("done");
});
});
});
});
콜백 지옥 해결 방법: Promise ~ then
// 프로미스: 내부적으로 콜백을 반환
const promise = new Promise((resolve, reject) => {});
- 프로미스 상태값: pending(대기), fulfill(이행), rejected(거부)
resolve
대기 → 이행 상태로 변경시켜야 합니다.
// 프로미스: 내부적으로 콜백을 반환
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 2000);
});
console.log(promise);
promise.then(() => {
console.log("순서가 보장되어 이행.");
});
console.log(promise);
- resolve가 호출되면 then()으로 넘겨받습니다.
- resolve 함수 호출 시 값을 넘겨줄 수도 있습니다.
// 프로미스: 내부적으로 콜백을 반환
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reolve("Congraturations");
}, 2000);
});
promise
.then((message) => {
console.log("순서가 보장되어 이행.", message);
});
console.log(promise);
reject
// 프로미스: 내부적으로 콜백을 반환
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject();
}, 2000);
});
console.log(promise);
promise
.then(() => {
console.log("순서가 보장되어 이행.");
})
.catch(() => {
console.log("에러입니다.😰");
});
console.log(promise);
- reject() 사용 시 catch() 메서드로 에러 처리가 가능합니다.
- reject() 함수 호출 시 인수로 값을 넘겨줄 수도 있습니다.
finally
promise
.then((message) => {
console.log("순서가 보장되어 이행.", message);
})
.catch(() => {
console.log("에러입니다.😰");
})
.finally(() => {
console.log("프로그램이 끝났습니다.");
});
- `finally`는 항상 실행되는 코드입니다.
콜백지옥 promise로 바꾸기
function task1() {
return new Promise((resolve) => {
console.log("task1");
resolve();
});
}
function task2() {
return new Promise((resolve) => {
console.log("task2");
resolve();
});
}
function task3() {
return new Promise((resolve) => {
console.log("task3");
resolve();
});
}
function task4() {
return new Promise((resolve) => {
console.log("task4");
resolve();
});
}
// task1().then(() => {
// console.log("task1 done");
// task2().then(() => {
// console.log("task2 done");
// task3().then(() => {
// console.log("task3 done");
// task4().then(() => {
// console.log("task4 done");
// console.log("done");
// });
// });
// });
// });
task1()
.then(() => task2())
.then(() => task3())
.then(() => task4())
.then(() => console.log("done"));
콜백지옥 promise로 바꾸고 에러 처리
function task1() {
return new Promise((resolve) => {
console.log("task1");
resolve();
});
}
function task2() {
return new Promise((resolve, reject) => {
console.log("task2");
reject("task2 error");
});
}
function task3() {
return new Promise((resolve) => {
console.log("task3");
resolve();
});
}
function task4() {
return new Promise((resolve) => {
console.log("task4");
resolve();
});
}
task1()
.then(() => task2())
.then(() => task3())
.then(() => task4())
.then(() => console.log("done"))
.catch((err) => {
console.error(err);
})
세부적으로 에러 처리
task1()
.then(() => task2())
.catch((err) => {
console.error(err);
})
.then(() => task3())
.then(() => task4())
.then(() => console.log("done"))
- 에러가 발생할 부분에 `catch`를 작성해주면 그 이후의 코드가 실행됩니다.
프로미스를 async, await로 바꾸기
// 프로미스
function getEmoji() {
new Promise((resolve, reject) => {
resolve("💕");
});
}
getEmoji().then((emoji) => console.log(emoji));
// async, await
async function getEmoji() {
//throw new Error("Error");
return "💕";
}
async function takeEmoji() {
const emoji= await getEmoji();
console.log(emoji);
}
pickEmoji();
async await 예제
function delay(ms, value) {
return new Promise((resolve) => setTimeout(() => resolve(value), ms));
}
async function getApple() {
await delay(2000);
return "🍏";
}
async function getCherry() {
await delay(4000);
return "🍒";
}
async function pickFruits() {
const apple = await getApple();
const cherry = await getCherry();
console.log(apple);
console.log(cherry);
}
pickFruits();
- pickFruits()를 호출하면 총 6초가 걸린 후에 결과가 출력됩니다.
병렬 처리로 데이터 받는 방법
function delay(ms, value) {
return new Promise((resolve) => setTimeout(() => resolve(value), ms));
}
async function getApple() {
await delay(2000);
return "🍏";
}
async function getCherry() {
await delay(4000);
return "🍒";
}
async function pickFruits() {
const appleData = getApple(); // pending
const cherryData = getCherry(); // pending
const apple = await appleData;
const cherry = await cherryData;
console.log(apple, cherry);
}
pickFruits();
`await` 키워드 없이 getApple(), getCherry()가 동시 호출을 시작하고 이는 pending 되어 있습니다. 이후에 데이터가 올 때까지 `await` 해주면 사과 2초, 체리 4초로 총 4초만 걸립니다.
async function pickFruits() {
const [apple, cherry] = await Promise.all([getApple(), getCherry()]);
console.log(apple, cherry);
}
Promise.all() 을 이용해서 `async` 함수를 병렬 처리가 가능합니다. 그만큼 서버의 자원을 많이 사용하는 단점이 있습니다. 4초 후 결과가 출력됩니다. 하나라도 에러가 나면 전체 정지가 되는 단점이 있어서 Promise.allSettled()를 사용해서 성공한 거라도 값을 받을 수 있습니다.
반응형
'프론트엔드 > JavaScript' 카테고리의 다른 글
[JavaScript] 이벤트 리스너 (0) | 2024.06.04 |
---|---|
[JavaScript] 클래스 (0) | 2024.06.03 |