비동기 자바스크립트
비동기 프로그램
다른 작업을 처리하고 다시 돌아와서 마무리
JS -> 비동기 프로그래밍이 많이 쓰임, 리퀘스트를 보내고 사용자와 상호작용해야하기 때문에 필요
비동기 프로그래밍을 하려면 꼭 알아야 하는 것
- 콜백 (CallBack)
-프로미스 (Promise)
파라미터(Parameter) vs 아규먼트(Argument)
function add(x, y) { //x, y 가 Parameter
return x + y;
}
add(1, 2); // 1,2 가 Argument
콜백(CallBack)
콜백 ;
어떤 함수의 아규먼트로 전달되는 함수
비동기 함수 (Asynchronous Function) ; 중간에 다른 작업을 처리하다가 다시 돌아와서 마무리 하는 함수
setTimeout(callback, delay) 함수
- setTimeout() 이전에 있는 코드 실행
- setTimeout() 함수 실행: delay 만큼 기다리는 타이머를 시작
- setTimeout() 이후에 있는 코드 실행
- delay가 지나면 callback 실행
-> 비동기가 동기보다 더 빨리 완료
console.log('1');
setTimeout(() => console.log('2'), 0);
console.log('3');
console.log('4');
console.log('5');
console.log('6');
console.log('7');
console.log('8');
console.log('9');
console.log('10');
//1
//3
//4
//5
//6
//7
//8
//9
//10
//2
setTimeout() 함수의 두 번째 파라미터로 0; 이건 콜백을 바로 실행하라는 뜻
-> 비동기 함수의 콜백은, 아무리 빨리 실행돼도 비동기 함수 이후에 있는 코드가 모두 실행된 후에 실행
-> 실행할 콜백이 여러 개일 경우, 동기적으로 실행
setInterval() 함수 ; 시간 간격을 두고 콜백을 반복적으로 실행
console.log('Start');
const intervalID = setInterval(() => console.log('2초가 지났습니다'), 2000);
// 7초 후에 setInterval() 해제
setTimeout(() => clearInterval(intervalID), 7000);
console.log('End');
//Start
//End
//2초가 지났습니다
//2초가 지났습니다
//2초가 지났습니다
clearInterval() 로 setInterval() 해제(멈춤)
DOM 의 addEventListener() 함수 ; 웹페이지 요소에 상호작용이 있을 경우 실행할 함수를 등록
const btn = document.querySelector('.my-btn');
btn.addEventListener('click', () => console.log('button clicked!'));
// ...
btn에 클릭('click') 이벤트가 발생할 시 () => console.log('button clicked!') 콜백이 실행
React의 useEffect() 함수 ; 컴포넌트가 모두 화면에 그려지는 시점에 콜백 실행
function PostList() {
// ...
useEffect(() => console.log('render finished!'), []);
return (
<div className="post-list">
<div className="post-item">...</div>
<div className="post-item">...</div>
<div className="post-item">...</div>
...
</div>
);
}
-> 콜백을 바로 실행하지 않고 일단 화면을 그리기 때문에 웹 페이지가 더 빨리 로딩되는 것처럼 보이게 할 수 있습니다.
Express의 get() 함수 ; 서버 내에서도 리퀘스트에 대한 처리를 비동기 형태로 진행
app.get('/hello', (req, res) => {
res.send('Success!');
});
// ...
콜백 헬(CallBack Hell)
작업을 이어서 하려면 콜백 안에 콜백을 등록해야 할때 콜백을 중첩해서 사용해야 하는 현상
-> Promise 등장
Promise
- 비동기 작업이 완료되면 값을 알려주는 객체
- 작업이 완료되면 값을 알려줄 것을 '약속'함
- fetch는 오래 걸려서 일단 Promise 를 돌려주고 나중에 작업이 완료되면 결과값을 Promise에 채워 넣어줌
- Pending: 비동기 작업이 끝나기를 기다릴 때
- Fulfilled: 비동기 작업이 성공적으로 끝났을 때. 비동기 작업의 성공 결과를 결과값으로 갖게 됨.
- Rejected: 비동기 작업이 실패했을 때. 비동기 작업에서 발생한 오류를 결과값으로 갖게 됨.
Promise를 다루는 방법
1. async 와 await 문법
await
const result = await Promise;
// 예시
const response = await fetch('https://learn.codeit.kr/api/employees');
await 은 promise 상태가 fulfilled(결과값 리턴), rejected(오류를 throw) 될 때까지 기다림
async
// 일반 function
async function printEmployees() {
const response = await fetch('https://learn.codeit.kr/api/employees');
const data = await response.json();
console.log(data);
}
// Arrow function
const printEmployees = async () => {
const response = await fetch('https://learn.codeit.kr/api/employees');
const data = await response.json();
console.log(data);
}
async 함수 안에서 await을 마주치면 함수 바깥으로 나가서 나머지 코드를 실행하다가 promise가 fulfilled/rejected 상태가 되면 다시 함수 안으로 돌아와 코드 실행
2. .then() 메소드 + 콜백
.then
앞선 Promise 객체가 fulfilled 상태가 될 때까지 기다렸다가 fulfilled 상태가 되면 안에 있는 콜백을 실행
앞선 Promise의 결과값을 콜백의 아규먼트로 전달. 앞선 Promise를 기다리는 동안에는 이후에 있는 코드를 실행.
그리고 .then()도 항상 Promise를 리턴.
- .then()안의 콜백이 Promise를 리턴할 경우 Promise를 그대로 리턴합니다.
- .then()안의 콜백이 평범한 값을 리턴할 경우 이 값을 결과값으로 가지는 Promise를 리턴합니다.
fetch('https://learn.codeit.kr/api/employees')
.then((response) => response.json())
.then((data) => console.log(data));
console.log('Task 2');
console.log('Task 3');
//Task 2
//Task 3
/*[
{
id: 1,
name: 'Jason',
email: 'jason@codeitmall.kr',
department: 'engineering'
},
...
]*/
.then vs await 의 try catch finally 메소드
Promise.all() 메소드
Promise.all([p1, p2, p3, ...])은 여러 Promise를 동시에 기다릴 때 사용
- 아규먼트로 전달된 Promise들이 모두 fulfilled 상태-> Promise.all()이 리턴하는 Promise도 fulfilled 상태가 됨. 아규먼트로 전달되는 Promise의 성공 결과값들로 이루어진 배열을 결과값 갖게 됨.
- 아규먼트로 전달된 Promise 중 하나라도 rejected 상태 -> Promise.all()이 리턴하는 Promise는 rejected 상태가 됨. rejected된 Promise의 결과값(오류)을 결괏값으로 갖게 됨.