https://learnjs.vlpt.us/async/01-promise.html
https://learnjs.vlpt.us/async/02-async-await.html
동기: 앞의 작업이 끝날 때까지 중지하고 기다림
비동기: 여러가지 작업을 멈추지 않고 처리
- 특정 작업이 진행되는 동안 다른 작업도 하고 싶다면 함수를 비동기 형태로 전환해야 함.
=> setTimeout 함수 사용 가능
setTimeout(() => { ... }, 0);
setTimeout: 첫번째 파라미터에 넣은 함수를 두번째 파라미터에 넣은 시간(ms) 이 흐른 후 호출하라는 의미
- 특정 함수가 끝난 다음 어떤 작업을 처리하고 싶을 때 (동기적, 즉 절차적으로 처리를 하고 싶을 때)
콜백 함수를 파라미터로 전달해서 특정 작업이 끝나고 호출
=> 함수 간 실행 순서를 잡아줄 수 있음
* 단, 콜백 함수로 처리하면 비동기 작업이 많아질 경우 코드가 쉽게 난잡해져서 ES6부터는 Promise 도입
흔히 아는 콜백 지옥을 생각하면 됨
function work(callback) {
setTimeout(() => {
...
console.log('특정 함수');
callback();
}, 0);
}
work(() => {
...
console.log('어떤 작업');
})
주로 비동기적으로 처리하는 작업들
- Ajax Web API 요청
서버 쪽에서 데이터 받아와야할 때는, 요청을 하고 서버에서 응답할때까지 대기해야하므로 비동기적으로 처리 - 파일 읽기
서버 쪽에서 파일 읽어야 하는 상황에 주로 비동기적으로 처리 - 암호화/복호화
바로 암호화/복호화가 되지 않고 시간이 어느정도 걸릴 수 있어 비동기적으로 처리 - 작업 예약
단순히 어떤 작업을 몇초 후에 스케줄링 해야하는 상황에 setTimeout 사용해 비동기적으로 처리
Promise
function increaseAndPrint(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const value = n + 1;
if (value === 5) {
const error = new Error();
error.name = 'ValueIsFiveError';
reject(error);
return;
}
console.log(value);
resolve(value);
}, 1000);
});
}
increaseAndPrint(0)
.then(increaseAndPrint) // increaeseAndPrint(1)
.then(increaseAndPrint) // increaeseAndPrint(2)
.then(increaseAndPrint) // increaeseAndPrint(3)
.then(increaseAndPrint) // increaeseAndPrint(4)
.then(increaseAndPrint) // increaeseAndPrint(5) => 결과값 에러
.catch(e => {
console.error(e);
});
- 비동기적으로 작업을 처리해야할 때 콜백 사용 시 코드의 깊이가 깊어지는 콜백 지옥이 생김.
promise를 사용하면 비동기 작업의 개수가 많아져도 코드 깊이가 깊어지지 않음.
- 성공 시 resolve 호출, 실패 시 reject 호출
- resolve 호출 시 파라미터로 특정 값 넣으면 작업이 끝나고 나서도 그 값 사용 가능
- 작업 끝나고 또 다른 작업해야할 때는 promise 뒤에 `.then(...)` 붙여서 사용
then 내부에 넣은 함수에서 또 promise를 리턴하면 연달아서 사용 가능
- reject는 사용하지 않으면 생략될 수 있음
promise의 불편한 점
- 에러 잡을 때 몇번째에서 발생했는지 알아내기 어려움
- 특정 조건에 따라 분기 나누는 작업 어려움
- 특정값 공유하면서 작업 처리하기 까다로움
=> 그래서 나온 대안책 : async/await
async / await
- ES8에 해당하는 문법으로, Promise를 더 쉽게 사용할 수 있게 함
- 함수 선언 시 함수 앞에 async 키워드를 붙이고 promise나 특정 함수 앞 부분에 await을 넣으면 해당 작업 끝날때까지 기다렸다가 다음 작업 수행 가능
- async 함수는 결과값을 Promise로 반환
- async 함수에서 에러 발생시킬 때 throw 사용 ( ex. throw new Error(); )
에러 잡을 때는 try/catch문 사용
- Promise.all : 여러 async 함수를 비동기로 실행하고 싶을 때 사용
주의) 등록한 promise 중 하나라도 실패하면 모두 실패로 간주
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const getDog = async () => {
await sleep(1000);
return '멍멍이';
};
const getRabbit = async () => {
await sleep(500);
return '토끼';
};
const getTurtle = async () => {
await sleep(3000);
return '거북이';
};
async function process() {
const results = await Promise.all([getDog(), getRabbit(), getTurtle()]);
console.log(results); // ["멍멍이", "토끼", "거북이"]
}
process();
* 각 함수 내에서 콘솔을 찍어보면 비동기적으로 실행되는 것을 관찰할 수 있다.
- Promise.race: 여러개의 promise를 등록해서 실행했을 때 가장 빨리 끝난 하나의 결과값만 가져옴
다른 Promise가 성공하기 전에 먼저 끝난 Promise가 실패하면 이를 실패로 간주함
'기타' 카테고리의 다른 글
[Github] Mac OS에서 Github에 프로젝트 올리기 (0) | 2022.08.31 |
---|---|
[웹 개발] 프론트와 백에서의 CORS 문제 해결하기 (0) | 2022.08.12 |
SQL과 NoSQL의 차이, 장단점 (0) | 2022.06.23 |
websocket과 socket.io 의 차이 (0) | 2022.06.22 |
[Sourcetree] Bitbucket 협업 시 충돌 병합(Conflict Merge) 해결 방법 (0) | 2022.06.07 |