일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 모던자바스크립트
- JavaScript
- 자바스크립트
- BAEKJOON
- 스택
- Ai
- 로보어드바이저
- 파이썬
- pyhton
- dfs
- Algorithm
- 백준
- 자료구조
- RPA
- 프로그래머스
- 큐
- Python
- 자문형
- 알고리즘
- algorithms
- BFS
- JS
- programmers
- frontend
- 혁신금융서비스
- SSAFY
- 일임형
- algoritms
- 신한투자증권
- React #Web #프런트엔드
- Today
- Total
Step by Step
비동기(Callback, Promise, Await, Async) 본문
Callback 함수는 이해하기가 정말 까다로웠다
함수 안에 함수를 호출하는데 작동 순서, 원리등을 이해하는데 꽤 오랜 시간이 걸렸다.
두번째 예시는 주로 강의에서 설명하던 방식인데 함수안에 저런 형태의 함수는 한번에 이해하기 힘들어서 첫번째 예시로 다시 만들어서 생각해보니 이해하기 훨씬 쉬웠다.
const add = (a, b, cb) => {
return cb(a + b);
};
const say = (val) => {
return console.log(val);
};
add(3, 4, say);
add 함수 안에 a,b,cb 인자를 받아주었는데 cb는 함수 인자이다.
작동 순서는 add(3,4,say)로 예시를 들면 3,4의 합을 say함수 인자로 받는다.
그 후 say 함수에서 console.log(val)로 console창에 출력을 해준다.
const add = (a, b, cb) => {
return cb(a + b);
};
add(3, 4, (val) => console.log(val));
쉽게 설명하면 (val) => console.log(val) 이 부분이 cb로 교체된다고 보면 된다.
return console.log(a+b) 이런 형식으로 바뀐다고 생각하니 이해가 쉬웠다.
Callback에서는 Callback 지옥이라는 표현이 있다.
아래 예시처럼 비동기적으로 코드를 적었을 때 함수 a,b,c,d 순서대로 호출하기 위해서는 a 함수를 실행한 후 callback으로 b를 받고 순차적으로 c,d를 받아 호출하는 경우가 있는데 이는 들여쓰기를 반복해서 가시성이 떨어진다는 단점이 있다.
const a = (callback) => {
setTimeout(() => {
console.log(1);
callback();
}, 1000);
};
const b = (callback) => {
setTimeout(() => {
console.log(2);
callback();
}, 1000);
};
const c = (callback) => {
setTimeout(() => {
console.log(3);
callback();
}, 1000);
};
const d = () => console.log(4);
a(() => {
b(() => {
c(() => {
d();
});
});
});
이런 단점을 고치기 위해 Promise 패턴을 사용하는데 callback 인수를 제거한 후 밑부분에 Promise를 선언한 후 인자값으로 resolve를 받는다. console.log(1) 부분 다음 줄에 resolve();를 삽입해 저 부분에서 다음 함수를 .then()문법을 사용해서 메소드 체이닝하는 것이다.
const a = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(1);
resolve();
}, 1000);
});
};
const b = () => console.log(2);
a().then(() => {
b();
});
const a = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(1);
resolve();
}, 1000);
});
};
const b = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(2);
resolve();
}, 1000);
});
};
const c = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(3);
resolve();
}, 1000);
});
};
const d = () => console.log(4);
//메소드 체이닝
a()
.then(() => b())
.then(() => c())
.then(() => d())
.then(() => console.log("done"));
위의 Callback, Promise 패턴보다 좀 더 간결한 문법이 있는데 이는 Await,Async이다.
똑같이 Promise를 사용하지만 .then()을 사용하지 않고 새로운 wrap함수는 만든 후 async로 묶어준 다음 호출하려는 함수 앞에 await을 사용하면 a함수가 실행되는 것을 기다린 후 a함수의 resolve()에서 b()가 실행되어 순차적으로 1,2가 콘솔창에서 출력되는것을 확인할 수 있다.
const a = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(1);
resolve();
}, 1000);
});
};
const b = () => console.log(2);
// a().then(() => {
// return b()
// })
const wrap = async () => {
await a(); //resolve 기다렸다가
b();
};
wrap();
Resolve, Rejcet 그리고 에러 핸들링을 알아보자.
아래 코드는 Promise를 사용하여 index 값이 10이하면 console.log(index), resolve(index+1) 코드가 실행된다.
delayAdd에 인자값 10일 넣어주면 10보다 크지 않으므로 출력값은 10, 11이 된다.
하지만 10보다 큰 13을 넣어주게 되면 if 조건문에서 조건을 만족하므로 reject문이 실행되어 '13는 10보다 클 수 없습니다' 라는 에러 메세지가 콘솔창에 나타나는 것을 확인할 수 있다.
delay(13).then().catch()문은 then에서 resolve문에 맞는 함수가 연결되고 catch에서 reject문에 맞는 함수가 연결된다.
const delayAdd = (index) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (index > 10) {
reject(`${index}는 10보다 클 수 없습니다`);
return;
}
console.log(index);
resolve(index + 1);
}, 1000);
});
};
delayAdd(13)
.then((res) => console.log(res))
.catch((err) => console.error(err));
Await, Async문을 활용할 수도 있다.
then()을 사용하는 대신 try문을 사용해서 await을 resolve와 연결할 수도 있다.
const delayAdd = (index) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (index > 10) {
reject(`${index}는 10보다 클 수 없습니다`);
return;
}
console.log(index);
resolve(index + 1);
}, 1000);
});
};
delayAdd(3)
.then((res) => console.log(res))
.catch((err) => console.error(err))
.finally(() => console.log("done"));
const wrap = async () => {
try {
const res = await delayAdd(3);
console.log(res);
} catch (err) {
console.error(err);
} finally {
console.log("done");
}
};
wrap();
강의를 들으면서 이해가 안되는 부분은 구조를 먼저 파악해 생각해보니 이해가 수월하게 되었던 것 같다.
'Javascript Study' 카테고리의 다른 글
모던자바스크립트 Deep Dive - 4장(변수) (0) | 2024.02.08 |
---|---|
Javascript - Web API (1) | 2023.11.21 |
Javascript 이벤트(addEventListener) (0) | 2023.11.18 |
Javascript 이벤트(추가, 삭제, 객체, 옵션, 버블링, 위임) (2) | 2023.09.09 |
DOM(Node, Element, 생성 , 검색, 수정)-(1) (0) | 2023.09.06 |