function func() {
setTimeout(() => {console.log(1)}, 6000)
setTimeout(() => {console.log(2)}, 3000)
setTimeout(() => {console.log(3)}, 1000)
}
func() // 3 2 1
async function asyncFunc() {
await new Promise((resolve) => setTimeout(() => {console.log(1); resolve()}, 6000))
await new Promise((resolve) => setTimeout(() => {console.log(2); resolve()}, 3000))
await new Promise((resolve) => setTimeout(() => {console.log(3); resolve()}, 1000))
}
asyncFunc() // 1 2 3
비동기 함수 func()
출력은 3, 2, 1 순서이며, 함수 실행 시간은 약 6초이다.
setTimeout은 비동기함수이며, setTimeout 함수를 포함한 func 함수 또한 비동기 함수이다. s
즉, 각각의 setTimeout에 설정한 시간이 모두 흘러갈 때 까지 기다리는 것이 아니라, 연속적으로 세 개의 setTimeout함수 스케쥴링을 진행한다.
때문에 timeout시간이 가장 빠른 3이 먼저 출력되고 그 이후에 2와 1이 출력된다.
그리고 총 함수 실행시간은 가장 긴 timeout시간을 가진 (약) 6초이다.
async 함수 asyncFunc()
출력은 1, 2, 3 순서이며, 함수 실행 시간은 약 10초이다.
Promise 앞에 사용된 await은 Promise가 settled 상태가 될 때 까지 기다린다. Promise가 settled 상태가 되면 resolve한 결과값을 반환한다.
즉 첫 setTimeout함수에서 6초를 기다린 후 console.log(1)을 실행하고 resovle를 실행한 후에, 두 번째 setTimeout 함수를 스케쥴링한다.
마치 동기 함수처럼 동작하며, 1, 2, 3 순서를 보장하며 실행된다. 하지만 모든 동작을 기다리는 만큼 함수 실생 시간은 10초가 걸린다.
// 함수 선언문
async function asyncFunc1() {
const response = await apiRequest();
console.log(response)
}
// 함수 표현식
const func = async function () {
const response = await apiRequest();
console.log(response)
}
// 화살표 함수
const asyncFunc2 = async () => {
const response = await apiRequest();
console.log(response)
}
await 키워드는 Promise가 settled 상태로 바뀌면서 resolve한 값을 반환한다.
Promise가 아닌 다른 코드 앞에 작성할 경우, 아무런 동작을 하지 않는다.
// 잘못된 예시
const func = async () => {
await setTimeout(() => {console.log('Hello')}, 1000)
console.log('world!')
}
func() // world! Hello
setTimeout은 비동기 함수이지만, Promise를 사용하지 않는다.
따라서 await 키워드가 정상동작하지 않는다.
// 적절한 예시
const func = async () => {
const message = await new Promise(resolve => setTimeout(() => {console.log('Hello'), resolve('world!')}, 1000))
console.log(message)
}
func() // Hellot world!
setTimeout함수가 스케쥴링 하고, await키워드는 Promise가 settled상태로 바뀔 때 까지 대기한다.
1초 뒤 'Hello'가 콘솔에 출력되고 resolve 함수를 실행하며 Promise는 settled 상태로 변한다.
이를 감지한 await은 resolve 반환값인 'world!' 문자열을 message에 반환한다.
그 다음에 console.log(message)를 실행하여 'world!'가 콘솔에 출력되게 된다.
async function getId() {
const response = await apiRequest(); // {id : 100}
return response.id
}
const findId = async () => {
const id = await getId()
console.log(id) // 100
}
위에서 말했듯이, await는 Promise를 반환하는 함수 앞에 사용될 수 있다.
getId는 Promsie를 반환하지 않고, response.id라는 값을 반환한다. 그런데 findId의 await는 getId가 값을 반환할 때 까지 기다리고, id 값을 정상적으로 출력한다.
그 이유는 async함수는 암묵적으로 반환값을 resolve하는 Promise를 반환하기 때문이다.
아래의 두 코드는 동일한 의미이다.
async function getId1() {
const response = await apiRequest(); // {id : 100}
return response.id
}
async function getId2() {
const response = await apiRequest(); // {id : 100}
return Promise.resolve(response.id)
}