비동기 호출
Callback이란?
- 다른 함수가 실행을 끝낸 뒤 실행되는 함수를 말한다.
- 즉, 코드를 통해 명시적으로 호출하는 함수가 아니라 함수를 등록해놓은 후 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출하는 함수를 말한다.
- 파라미터로 함수를 전달 받아 함수의 내부에서 실행된다.
콜백함수의 사용 이유
- Js에서 비동기적 프로그래밍을 할 수 있기 때문이다.
- Js는 싱글스레드를 사용하는데 멈춤을 방지해준다. 즉 블록킹을 방지하여 싱글스레드가 논블록킹으로 동작하게 한다.
💡 싱글스레드 : 싱글스레드는 한 번에 하나의 작업만 수행할 수 있다.
💡 싱글스레드로 어떻게 비동기 작업이 가능할까?
- 자바스크립트의 메인스레드인 이벤트 루프가 싱글스레드이기 때문에 자바스크립트를 싱글스레드 언어라고 부른다. 그러나 자바스크립트는 이벤트 루프만 독립적으로 실행하지는 않고 웹 브라우저나, NodeJs같은 멀티 쓰레드 환경에서 실행된다.
- 즉 동시성을 보장하는 비동기, 논블록킹 작업들은 Js엔진을 구동하는 웹 브라우저, NodeJs에서 담당한다.
콜백함수의 사용 유형
- 익명 함수 사용
- 콜백함수는 이름 없는 "익명의 함수"를 사용한다. 함수의 내부에서 실행되기 때문에 이름을 붙이지 않아도 된다.
- 함수의 이름 넘기기
- 자바스크립트는 null과 undefined 타입을 제외하고 모든 것을 객체로 다룬다. 함수를 변수 또는 다른 함수의 변수처럼 사용할 수 있다. 함수를 콜백함수로 사용할 경우 함수의 이름만 넘겨주면 된다.
- 전역변수, 지역변수를 콜백함수의 파라미터로 전달가능
- 전역 변수 : 함수 외부에서 선언된 변수
- 지역 변수 : 함수 내부에서 선언된 변수
콜백함수의 주의점
this를 사용한 콜백함수의 콜백 지옥
- 콜백지옥은 콜백함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들정도로 깊어지는 현상이다.
- 주로 이벤트 처리나 서버 통신과 같은 비동기 적인 작업을 수행하기 위해 이런 형태가 자주 등장하는데, 가독성이 떨어지면서 코드를 수정하기 어려워진다.
- 비동기적인 작업을 수행하기 위해 콜백함수를 익명함수로 전달하는 과정에서 생기는 콜백지옥을 Promise, async/await, Generator 등을 사용해 방지할 수 있다.
Promise란?
- Promise는 Js비동기처리에 사용되는 객체이다.
- 싱글스레드인 자바스크립트에서 비동기 처리를 위해 사용한 콜백함수의 에러/예외처리의 어려무, 중첩으로 인한 복잡도 증가라는 단점을 해결하기 위해 프로미스 객체를 ES6에서 언어적 차원으로 지원한다.
💡 Promise가 콜백을 대체하는것은 아니지만 콜백을 예측가능한 패턴으로 사용할 수 있게 하며 Promise없이 콜백만 사용했을 때 예상치 못한 동작을 막아주거나 힘든 버그를 상당 수 해결해 준다.
Promise 만들기
const promise = new Promise((resolve, reject) => {
})
const promise = new Promise((resolve, reject) => {
})
promise.then(
)
.catch(
)
.finally(
)
- Promise 다음엔 then()과 catch()를 사용한다.
- then()은 생성한 프로미스 객체에서 인수로 전달한 resolve가 호출되면 실행된다.
- catch()는 생성한 프로미스 객체에서 인수로 전달한 reject가 호출되면 실행된다.
Promise 객체로 비동기 처리 연결하기
then()과 catch()뒤에 또다른 then()과 catch를 연결함으로써 비동기 처리를 연결할 수 있다.
const promise = new Promise((resolve, reject) => {
})
promise.then( (data) => {
return new Promise((resolve, reject) => {
}). then((data2) => {
}).catch(
console.log(ErrorMessage)
)
})
.catch(
console.log(ErrorMessage)
)
Promise의 3가지 상태
- Promise의 상태란 처리과정을 의미한다.
- new Promise()로 생성하고 종료될 때까지 3가지 상태를 갖는다.
- Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태.
- Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과값을 반환해준 상태.
- Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태.
async & await
async & await란?
- async & await는 비동기식 코드를 동기식으로 표현하여 간단하게 나타내는 것이다.
- 기존의 비동기 처리 방식인 콜백함수의 단점을 보완하기 위해 Promise를 사용했지만, 코드가 장황하다는 단점이 있었다.
- 이러한 단점을 해결하기 위해 ES8에서 도입된 비동기 처리 방식의 가장 최신 문법이다.
- async & await는 Promise객체를 반환한다.(then()을 사용할 수 있다.)
async & await 기본 문법
async function 함수명(){
await 비동기_처리_메소드_이름()
}
- 함수의 앞에 async라는 예약어를 붙인다.
- 함수의 내부로직중 HTTP통신을 하는 비동기 처리 코드 앞에 await을 붙인다.
- 비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await가 의도한 대로 동작한다.
- 일반적으로 await의 대상이 되는 비동기 처리 코드는 Axios등 프로미스를 반환하는 API호출 함수이다.
1. async 함수
- async는 function 앞에 위치한다.
- function앞에 async를 붙이면 해당 함수는 항상 프로미스를 반환한다.
- Promise가 아닌 값을 반환하더라도 이행상태의 Promise로 값을 감싸 이행된 프로미스가 반환되도록 한다.
- async 함수는 화살표 함수, 함수 표현식으로도 정의가 가능하다.
2. await
- await은 async함수 안에서만 동작한다.
- Js는 await을 만나면 Promise처리가 될 때까지 기다리고 결과는 그 이후에 반환된다.
async & await 예제
function delay(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple(){
await delay(2000)
return "Apple"
}
async function getBanana(){
await delay(1000)
return "Banana"
}
getApple().then((data) => console.log(data))
getBanana().then((data) => console.log(data))
async & await의 예외처리
- async & await에서 예외처리를 하는 방법은 try와 catch를 사용하는 것이다.
- catch{}를 사용하면 된다.
function Data() {
return new Promise((resolve, reject) => {
setTimeout(() => {
return resolve('성공')
}, 1000)
})
}
async function loadData(){
try{
const result = await Data()
console.log(result)
} catch(e){
console.log(e)
}
}
loadData()