그렇다면, Ajax 요청, 이벤트 리스너,
SetTimeout
등 처리하는데 시간이 오래 걸리는 작업들을 계속 기다려야 하는가?
위와 같은 작업들은 자바스크립트 엔진이 아닌, 브라우저 내부의 멀티 스레드인 Web APIs에서 비동기 + 논블로킹으로 처리된다.
➜ 비동기의 핵심 요소는 JS가 아니라 브라우저이다.
⚠️ Node.js에서는 libuv 내장 라이브러리가 처리한다.
이벤트 루프
: 브라우저의 동작 타이밍을 제어하는 관리자
이벤트 루프를 통해서 JS 코드를 멀티스레드처럼 동작하게 만들 수 있다.
⚠️ Call Stack 이 비었을 때만 Queue에서 올린다!!
콜백 함수
: 다른 함수에 인자로 전달되는 함수.
주로 비동기적 작업이 완료된 후에 호출되거나, 특정 이벤트가 발생했을 때 실행된다.
왜 필요할까?
➜ 비동기 방식은 순서를 보장하지 않기 때문에, 응답의 처리 결과에 의존하는 콜백 함수를 이용해서 순서를 간접적으로 끼워맞출 수 있다.
단점은?
➜ 코드 복잡도를 증가시킨다.
Promise 객체
: 비동기 작업이 끝나면 그 결과에 따라 하나의 값을 반환하는 객체
Promise 객체를 사용하면, 콜백 함수를 사용할 때의 코드 복잡도를 개선할 수 있다.
new Promise(콜백 함수)
로 생성할 수 있다.new Promise(콜백 함수)
에서 콜백 함수는 두 개의 매개변수를 필요로 한다.const myPromise = new Promise((resolve, reject) => {
// 비동기 작업 수행
const data = fetch('URL');
if(data)
resolve(data); // 만일 요청이 성공하여 데이터가 있다면
else
reject("Error"); // 만일 요청이 실패하여 데이터가 없다면
})
위의 작업으로 만들어진 myPromise
객체는 비동기 작업이 완료된 이후에 수행될 다음 작업을 연결할 수 있다.
➜ 콜백 함수가 했던 것처럼 순서 보장을 해준다.
⚠️
new Promise
가 생성되면, Promise의 매개변수로 넘겨준 콜백함수는 자동적으로 & Synchronous 하게 실행된다.
하지만, 그 내부에서는 Asynchronous 하기 때문에 비동기적으로 작업이 수행된다.
.then()
과 .catch()
메소드 체이닝을 통해 성공과 실패에 대한 후속 처리를 할 수 있다.
myPromise
.then((value) => { // 성공적으로 수행했을 때 실행될 코드
console.log("Data: ", value); // 위에서 return resolve(data)의 data값이 출력된다
})
.catch((error) => { // 실패했을 때 실행될 코드
console.error(error); // 위에서 return reject("Error")의 "Error"가 출력된다
})
.finally(() => { // 성공하든 실패하든 무조건 실행될 코드
})
.then()
, .catch()
의 리턴 값은 Promise
객체이다.
➜ .then()
의 결과 값에 다시 .then()
를 붙일 수 있다!
하지만 프로미스도 완벽한 해결책은 아니다.
➜ 지나친 then 핸들러 함수의 남용으로 인한 Promise Hell 발생 가능
async/await
: 비동기 코드를 마치 동기 코드처럼 쉽고 명확하게 작성할 수 있게 만들어 주는 키워드.
Promise를 기반으로 한다.
아래 코드는 async/await을 사용하지 않은 코드이다.
// 기존 Promise.then() 형식
// 프로미스 객체 반환 함수
function delay(ms) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`${ms} 밀리초가 지났습니다.`);
resolve()
}, ms);
});
}
function main() {
delay(1000)
.then(() => {
return delay(2000);
})
.then(() => {
return Promise.resolve('끝');
})
.then(result => {
console.log(result);
});
}
// 메인 함수 호출
main();
아래의 코드는 async/await을 사용한 코드이다.
// async/await 방식
async function main() {
await delay(1000);
await delay(2000);
const result = await Promise.resolve('끝');
console.log(result);
}
// 메인 함수 호출
main();
https://inpa.tistory.com/entry/JS-📚-비동기처리-Promise [Inpa Dev 👨💻:티스토리]