1. timeout
- 동기식 (순차적 실행)
프로그램 흐름에 시간(노드)이 걸려있어도 일단 마무리하고 다음으로 프로그램 진행
< js >
function func1(){
for(let i=0; i<10000000000; i++);
return 10;
}
function func2(){
return func1() + 10;
}
function func3(){
return func2() + 10;
}
console.log('프로그램이 시작됩니다.')
const result = func3();
console.log(result);
</js >
프로그램이 시작됩니다 30 |
- 비동기식 (동시 다발적 실행)
프로그램을 실행할 때 시간이 걸리거나 대기시간이 있다면 다음 문장을 미리하고 다시 돌아옴
< js >
//timeout
function timeout() {
console.log('1번 문장 실행!');
setTimeout(() => {
console.log('2번 문장 실행!');
}, 3000) //3초 후의 실행 // 화살표함수: 비동기
console.log('3번 문장 실행!');
}
timeout();
</js >
1번 문장 실행! 3번 문장 실행! 2번 문장 실행! |
- 문제
주어진 초가 지나면 callback 함수를 호출하는 함수 작성해보자
(단 주어진 초가 0보다 작으면 에러 발생, callback 함수가 없으면 에러 발생)
< js >
function run(callback, seconds){
if (!callback) { //콜백함수가 없어서 false라면
throw new Error('callback 함수가 없습니다');
}
if (!seconds || seconds < 0) { //초가 넘어오지 않거나 초가 0보다 작다면
throw new Error('seconds는 0보다 커야함');
}
setTimeout(callback, seconds); //콜백함수, 초 넘겨주기
}
// run 실행 : ( 화살표함수:익명함수, 3초)
run(() => { console.log('타이머 완료!'); }, 3000); //3초 뒤에 '타이머 완료'
//run(() => { console.log('타이머 완료!'); }, -3000); //에러
console.log('----------------------------')
// 오류처리(3000 입력)
try {
run(() => { console.log('타이머 완료!'); }, 3000); /3초 뒤에 '타이머 완료'
} catch (error) {//에러를 발생하는 문장
console.log(error);
console.log('에러발생 후 정상적인 종료');
}
console.log('----------------------------')
// 오류처리(-3000 입력
try {
run(() => { console.log('타이머 완료!'); }, -3000); /에러
} catch (error) {//에러를 발생하는 문장
console.log(error);
console.log('에러발생 후 정상적인 종료');
}
</js >
/3초 뒤/ 타이머 완료! --------------------------------------------- /3초 뒤/ 타이머 완료! Error: seconds는 0보다 커야함 at run (C:\Sarr\KDT\Web\JavaScript\Day6\1_timeout.js:40:23) at Object.<anonymous> (C:\Sarr\KDT\Web\JavaScript\Day6\1_timeout.js:51:13) at Module._compile (node:internal/modules/cjs/loader:1369:14) at Module._extensions..js (node:internal/modules/cjs/loader:1427:10) at Module.load (node:internal/modules/cjs/loader:1206:32) at Module._load (node:internal/modules/cjs/loader:1022:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12) at node:internal/main/run_main_module:28:49 에러발생 후 정상적인 종료 타이머 완료! |
2. Promise
- 비동기 (특정작업이 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있음)
- 작업을 다루는 객체
- 프로미스 상태
- 대기: 비동기 작업이 아직 수행되지 않은 상태
- 이행: 비동기 작업이 성공적으로 완료된 상태. resolve() 호출
- 거부: 비동기 작업이 실패한 상태. reject() 호출
const myPromise = new Promise((resolve, reject) => {
// 비동기 작업 수행
// 작업이 성공하면 resolve() 호출
// 작업이 실패하면 reject() 호출
});
myPromise
.then((result) => {
// 성공했을 때의 처리
})
.catch((error) => {
// 실패했을 때의 처리
});
- 원래 함수 ( Promise 전 )
//콜백지옥 (원래)
getUserInfo(userid,(user)=>{
getPosts(user.id, (posts) =>{
displayPosts(posts);
}, (error)=> {
handleError(error);
});
}, (error)=> {
handleError(error);
});
//바꿔보기
getUserInofo(userid)
.then((user)=>{
return getPosts(user.id);
})
.then((posts) => {
displayPost(posts);
})
.catch((error)=>{
handleError(error);
});
- Promise로 바꿔보기
< js >
function run(callback, seconds){
if (!callback) {
throw new Error('callback 함수가 없습니다');
}
if (!seconds || seconds < 0) {
throw new Error('seconds는 0보다 커야함');
}
setTimeout(callback, seconds);
}
[Promise로 바꿔주기]
_ 콜백함수 겹쳐쓰지 않아도 됨
_ 가독성이 좋음
_ 콜백함수 겹쳐쓰지 않아도 됨
_ 가독성이 좋음
function run(seconds) {
return new Promise((resolve, reject) => {
if (!seconds || seconds < 0) {
reject(new Error('seconds가 0보다 작음!'));
}
setTimeout(resolve, seconds);
})
}
run(3000)
.then(() => console.log('타이머 완료!')) //성공했다면
.catch(console.error) //오류라면
.finally(() => console.log('프로그램 종료!')); //끝냈다면
</js >
/3초 뒤/ 타이머 완료! 프로그램 종료! |
- Promise 활용(1)
< js >
function fetchEgg(chicken) {
return Promise.resolve(`${chicken}=>🥚`)
}
function fryEgg(egg) {
return Promise.resolve(`${egg}=>🍳`);
}
function getChicken() {
//return Promise.resolve('🐓=>🍗'); // 🐓=>🍗=>🥚=>🍳 //첫번째 결과
return Promise.reject(new Error('치킨을 가지고 올 수 없음!')); // 🐔=>🥚=>🍳
}
getChicken()
.catch(() => '🐔')
.then(fetchEgg) //getChicken()성공시 fetchEgg()호출!
.then(fryEgg) //fetchEgg()성공시 fryEgg()호출!
.then(console.log); //fryEgg() 실행!
</js >
첫번째 결과 : 🐓=>🍗=>🥚=>🍳 두번째 결과 : 🐔=>🥚=>🍳 ----------------------------------------- .catch(() => '🐔') 두번째인 경우 🐔 =>🍳 .catch(() => '🐔') 세번째인 경우 🐔 |
- Promise 활용(2)
< js >
function getBanana() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('🍌');
}, 1000);
});
}
function getApple() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('🍎');
}, 3000);
});
}
function getOrange() {
return Promise.reject(new Error('오렌지 없음!'));
}
</js >
/4초 뒤/ [ '🍌', '🍎' ] |
- Promise 활용(3)
< js >
// Promise.all: 병렬적으로 한 번에 Promise들을 실행
Promise.all([getBanana(), getApple()])
.then((fruits) => console.log('all', fruits)); //3초 뒤 //all [ '🍌', '🍎' ]
</js >
/3초 뒤/ all [ '🍌', '🍎' ] /4초 뒤/ [ '🍌', '🍎' ] |
- Promise 활용(4)
< js >
// Promise.race: 주어신 Promise중에 제일 빨리 수행된 것이 실행
Promise.race([getBanana(), getApple()])
.then((fruit) => console.log('race', fruit)); //race 🍌
</js >
/ 먼저 실행/ race 🍌 /3초 뒤/ all [ '🍌', '🍎' ] /4초 뒤/ [ '🍌', '🍎' ] |
- Promise 활용(5)
< js >
// promise all은 하나의 promise라도 실패하면 에러로 처리
// 하나라도 실패하면 걍 catch로 가버림
Promise.all([getBanana(), getApple(), getOrange()])
.then((fruits) => console.log('all', fruits))
.catch(console.log);
</js >
Error: 오렌지 없음! at getOrange (C:\Sarr\KDT\Web\JavaScript\Day6\4_promise-all.js:18:35) at Object.<anonymous> (C:\Sarr\KDT\Web\JavaScript\Day6\4_promise-all.js:40:39) at Module._compile (node:internal/modules/cjs/loader:1369:14) at Module._extensions..js (node:internal/modules/cjs/loader:1427:10) at Module.load (node:internal/modules/cjs/loader:1206:32) at Module._load (node:internal/modules/cjs/loader:1022:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12) at node:internal/main/run_main_module:28:49 / 먼저 실행 / race 🍌 / 3초 뒤 / all [ '🍌', '🍎' ] / 4초 뒤 / [ '🍌', '🍎' ] |
- Promise 활용(5)
< js >
// settled는 여러 프로미스를 병렬적으로 처리하되 하나의 프로미스가 실패해도 무조건 이행
Promise.allSettled([getBanana(), getApple(), getOrange()])
.then((fruits) => console.log('all', fruits))
.catch(console.log);
</js >
Error: 오렌지 없음! at getOrange (C:\Sarr\KDT\Web\JavaScript\Day6\4_promise-all.js:18:35) at Object. (C:\Sarr\KDT\Web\JavaScript\Day6\4_promise-all.js:40:39) at Module._compile (node:internal/modules/cjs/loader:1369:14) at Module._extensions..js (node:internal/modules/cjs/loader:1427:10) at Module.load (node:internal/modules/cjs/loader:1206:32) at Module._load (node:internal/modules/cjs/loader:1022:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12) at node:internal/main/run_main_module:28:49 / 먼저 실행 / race 🍌 / 3초 뒤 / all [ '🍌', '🍎' ] / 상태 추가 / all [ { status: 'fulfilled', value: '🍌' }, { status: 'fulfilled', value: '🍎' }, { status: 'rejected', reason: Error: 오렌지 없음! at getOrange (C:\Sarr\KDT\Web\JavaScript\Day6\4_promise-all.js:18:35) at Object.<anonymous> (C:\Sarr\KDT\Web\JavaScript\Day6\4_promise-all.js:47:54) at Module._compile (node:internal/modules/cjs/loader:1369:14) at Module._extensions..js (node:internal/modules/cjs/loader:1427:10) at Module.load (node:internal/modules/cjs/loader:1206:32) at Module._load (node:internal/modules/cjs/loader:1022:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12) at node:internal/main/run_main_module:28:49 } ] / 4초 뒤 / [ '🍌', '🍎' ] |
3. async / await
- 자바 스크립트에서 비동기 코드를 더 쉽게 작성하고 관리할 수 있는 기능
- 비동기 작업이 순차적으로 실행되는 것처럼 코드를 작성할 수 있음
- async 함수는 항상 promise를 반환하여, await 키워드는 async 함수 내에서만 사용
- async 활용(1)
* 비동기 함수를 순차적으로 실행하기
- 방법: 순차적으로 실행한 후에 묶어서 호출
- 사용이유: 비동기라 하더라도 순차적으로 실행해야 하는 경우가 많음
< js >
function getBanana() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('🍌');
}, 1000);
});
}
function getApple() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('🍎');
}, 3000);
});
}
function getOrange() {
return Promise.reject(new Error('오렌지 없다!'));
}
// 바나나와 사과를 같이 가지고 오는 async 함수 만들기
// 방법: 순차적으로 실행한 후에 묶어서 호출
// 비동기라 하더라도 순차적으로 실행해야 하는 경우가 많음
async function fetchFruits() {
const banana = await getBanana();
// 비동기함수 getBanna실행값이 banana에 담김
const apple = await getApple();
// 비동기함수 getApple실행값이 banana에 담김
return [banana, apple];
}
fetchFruits().then((fruits) => console.log(fruits))
// 정상적으로 끝났다면 fruits 출력
</js >
[ '🍌', '🍎' ] |
- async 활용(2) _ Promise-egg 코드 바꿔보기
< js >
function fetchEgg(chicken) {
return Promise.resolve(`${chicken}=>🥚`)
}
function fryEgg(egg) {
return Promise.resolve(`${egg}=>🍳`);
}
function getChicken() {
return Promise.reject(new Error('치킨을 가지고 올 수 없음!'));
}
async function makeFriedEgg() {
let chicken;
try {
chicken = await getChicken()
} catch {
chicken = '🐔';
const egg = await fetchEgg(chicken);
return fryEgg(egg);
}
}
makeFriedEgg().then(console.log)
</js >
🐔=>🥚=>🍳 |
'Web > Node.js' 카테고리의 다른 글
06. 버퍼(buffer), 스트림(Steam) (0) | 2024.04.24 |
---|---|
05. Console, This, file (0) | 2024.04.23 |
04. JSON (0) | 2024.04.23 |
02. 이터레이터, 이터러블, 스프레드 (0) | 2024.04.19 |
01. Node.js (0) | 2024.04.19 |