async function getProduct(id) {
// (...) 사전준비코드생략
const res = await fetch(`https://api.excuelajs.co/api/v1/products/${id}`)
const json = await res.json()
return json
}
async function handleChange(e) {
const id = e.target.value
const product = await getProduct(id)
renderProduct(product)
}
fetch 관련된 부분만 별도로 빼기 (global 함수로 추출)
async function fetchProduct(id) {
const res = await fetch(`https://api.excuelajs.co/api/v1/products/${id}`)
const json = await res.json()
return json
}
async function getProduct(id) {
const json = fetchProduct(id)
return json
}
async function handleChange(e) {
const id = e.target.value
const product = await getProduct(id)
renderProduct(product)
}
추출하고 나니 async가 붙은 함수가 세 개가 됐음. getProduct는 중간 함수가 된 것으로 사실상 async/await 명령어가 전혀 필요가 없게 됨. 왜냐면 얘는 fetchProduct를 호출한 응답 값을 json으로 그대로 리턴해주는 역할
async function fetchProduct(id) {
const res = await fetch(`https://api.excuelajs.co/api/v1/products/${id}`)
const json = await res.json()
return json
}
function getProduct(id) {
const json = fetchProduct(id)
return json
}
이미 응답값 자체가 Promise니까 async/await가 없더라도 아무런 문제가 없게됨.
const fetchProduct = id =>
fetch(`https://api.excuelajs.co/api/v1/products/${id}`).then(res => res.json())
fetch를 하고 그 응답값으로부터 json을 추출하는 과정은 다른 모든 api 통신에서 다 범용적으로 쓰일 수 있는 녀석
const fetchJson = url => fetch(url).then(res => res.json())
const fetchProduct = id => fetchJson(`https://api.excuelajs.co/api/v1/products/${id}`)
중간 과정에서는 async/await가 없어도 괜찮음
마지막에 전달되는 최종 결과물이 promise 이면 그 종착지에서 비동기 처리가 이루어질테니 프로미스가 넘어온다는 것만 확인되면 그 중간에선 async/await 명령어가 없어도 무방
간단하게 then으로 처리할 수 있는 경우에도 없앨 수 있음
async/await는 기존 비동기 처리가 주는 불편함을 해소하기 위해 등장한 만큼, 어디선가 최소 한 번은 쓰는 게 좋다. 그렇지만 중간 과정상에 있는 함수 전부에서 사용해야 하는 것은 아님
async/await는 비동기처리를 단순화한 편의 문법으로, 문제 없이 동작하면 마구 써도 괜찮음. 다만 함수를 async로 만든다는 것은 원래의 함수를 promise로 감싸는 것임을 염두
Promise를 여러 번 감싼다고 해서 microTaskQueue가 감당을 못하는 것은 아니라 성능 저하를 일으킬 경우는 드물겠지만, 어쨌든 비동기 제어가 반드시 필요한 것이 아님에도 표기하는 자체로 협업하는 팀원들 사이에서는 "반드시 비동기 처리를 동기적으로 마친 후에야 다음 코드로 진행해야 한다"라는 오해를 불러일으킬 가능성이 농후하니 가급적 주의를 기울이는 것이 좋음.
async/await를 지워도 괜찮은가? 를 판단하는 기준