•
Promise & Async/await은 callback 보다 코드 작성 및 타입 추론에 유리
•
Async/await은 promise 보다 직관적 & 간결 & 오류 제거
•
Promise 반환 함수는 async 선언이 유리
1. Promise & Async/await의 장점
•
콜백보다 코드 작성이 쉬움 + 타입 추론에 유리
// 병렬로 페이지 로드를 원할 시 Promise.All 사용해 구현 가능
// response* 변수의 타입을 response로 추론
async function fetchPages() {
const [response1, response2, response3]
= await Promise.all([fetch(url1), fetch(url2), fetch(url3)])
// ...
}
// 콜백 스타일로 작성하려면 구문 및 타입 코드가 늘어남
function fetchPagesCB() {
let numDone = 0
const responses: string[] = []
const done = () => {
const [response1, response2, response3] = responses
// ...
}
const urls = [url1, url2, url3]
urls.forEach((url, i) => {
fetchURL(url, r => {
responses[i] = url
numDone++
if (numDone === urls.length) done()
})
})
}
// Promise.race도 타입 추론과 잘 맞음
// Promise.race: 병렬로 실행하되 가장 빨리 실행된 것만 resolve
// timeout의 type은 never (return이 없거나 항상 오류 반환)
function timeout(millis: number): Promise<never> {
return new Promise((resolve, reject) => {
setTimeout(() => reject('timeout'), millis)
})
}
async function fetchWithTimeout(url: string, ms: number) {
return Promise.race([fetch(url), timeout(ms)])
}
TypeScript
복사
2. Async/await의 Promise 대비 장점
•
async는 항상 promise를 반환하도록 강제
// function getNumber(): Promise<number>
async function getNumber() {
return 42
}
const getNumber = async () => 42 // Type is () => Promise<number>
const getNumber = () => Promise.resolve(42) // Type is () => Promise<number>
TypeScript
복사
•
Promise 반환 강제는 함수의 통일성에 도움이 됨(동기/비동기 측면)
// 함수는 항상 동기 또는 비동기로 실행되어야 함
// 잘못된 예시
// 캐시되어 있다면 requestStatus는 success 이후에 loading으로 돌아감
const _cache: { [url: string]: string } = {}
function fetchWithCache(url: string, callback: (text: string) => void) {
if (url in _cache) {
callback(_cache[url])
} else {
fetchURL(url, text => {
_cache[url] = text
callback(text)
})
}
}
let requestStatus: 'loading' | 'success' | 'error'
function getUser(userId: string) {
fetchWithCache(`/user/${userId}`, profile => {
requestStatus = 'success'
})
requestStatus = 'loading'
}
// async로 리팩토링
// 이제 requestedStatus가 success로 끝나는 것이 명백
async function fetchWithCache(url: string) {
if (url in _cache) {
return _cache[url]
}
const response = await fetch(url)
const text = await response.text()
_cache[url] = text
return text
}
let requestStatus: 'loading' | 'success' | 'error'
async function getUser(userId: string) {
requestStatus = 'loading'
const profile = await fetchWithCache(`/user/${userId}`)
requestStatus = 'success'
}
TypeScript
복사
•
async 함수에서 promise 반환 시 추가적인 promise로 래핑되지 않음
// Function getJSON(url: string): Promise<any>
async function getJSON(url: string) {
const response = await fetch(url)
const jsonPromise = response.json() // Type is Promise<any>
return jsonPromise
}
TypeScript
복사