턱걸이를 시작한지 일주일도 안 되었는데 횟수가 2개에서 4개로 무려 2배나 늘었다. 이정도 기세라면 턱걸이 세계 챔피언을 노려 볼 수 있지 않을까 싶다. 개발 공부는 때려치고 턱걸이 선수의 길을 알아봐야겠다.
자바스크립트는 기본적으로 비동기적 처리를 지원한다.
동기적으로 처리하는 방법은 3초 걸리는 task1, 1초 걸리는 task2, 5초 걸리는 task3가 있다면
순서대로 task1을 마무리 하고 task2가 실행되고 task2가 처리되고 task3가 실행된다.
즉, 모든 task를 처리하는데 9초가 소요된다.
비동기는 task를 순서대로 처리하지 않고 다음 코드를 바로 실행한다.
task1이 실행되고 완료되지 않아도 task2가 실행되고 task2가 완료되지 않아도 task3가 실행된다.
즉, 모든 task를 처리하는데 5초가 소요된다.
완료되는 순서는 task2, task1, task3가 된다.
그럼 언제 끝날지 모르는 task를 비동기적으로 처리한다면 어떻게 될까?
task2가 먼저 나올지 task3이 먼저 나올지 알 수가 없다.
그런데 난 task의 순서를 제어하고 싶은데???
이럴 때 활용 할 수 있는 방법이 총 3가지가 있다.
task1이 끝나고 callback함수로 task2를 실행시키는 방식이다.
const doTask = (task, callback) => {
setTimeout(
() => {
console.log(task) // task를 실행해주고
callback() // callback 함수를 실행
// 이 callback 함수에는 다음 task를 실행시킬 함수가 들어있겠죠?
},
Math.floor(Math.random() * 100) + 1
)
}
const doAllTask = () => {
doTask('task1', () => {
doTask('task2', () => {
doTask('task3', () => {})
})
})
}
doAllTask() // 'task1', 'task2', 'task3'
이게 약간 Promise라는 클래스로 인스턴스를 만들어서 then, catch, finally 같은 메소드를 사용 할 수 있는데 이 then이 아주 기가맥힌다.
위의 callback형태로 쓴 함수를 Promise형태로 바꾸어보겠다.
const doTask = (task) => {
return new Promise ((resolve, reject) => { // 매개변수로 resolve, reject 두 개를 받는다
setTimeout(
() => {
console.log(task)
resolve() // 함수가 성공적으로 완료되면 resolve
},
Math.floor(Math.random() * 100) + 1
)
})
}
const doAllTask = () => {
doTask('task1') // task1 실행
.then(() => { // task1이 완료될 때까지 기다리고
return doTask('task2') // task2 실행
})
.then(() => { // task2가 완료될 때까지 기다리고
return doTask('task3') // task3 실행
})
}
doAllTask()
Promise는 callback이 실행될 때마다 다음 task로 넘어가는 방식이 아니라
.then으로 다음 함수를 실행시키고 있다.
여기서 .then은 Promise가 정상적으로 수행이 된다면 Promise와 resolve를 가져온다.
그리거 .then에서 return해주면 다음 .then에서 그 리턴한 값을 가져온다.
.then에서 리턴한 것은 Promise에서 리턴 된 것과 같다.
배열 객체
각각의 task로서 배열 순서대로 비동기 실행이 된다.
여러번 Promise 처리하기 번거롭기 때문에 한 번에 비동기 처리하기 위해 사용된다.
const doTask = (task) => {
return new Promise ((resolve, reject) => { // 매개변수로 resolve, reject 두 개를 받는다
setTimeout(
() => {
resolve(console.log(task)) // 함수가 성공적으로 완료되면 resolve
},
Math.floor(Math.random() * 100) + 1
)
})
}
const doAllTask = () => {
return Promise.all([doTask('task1'), doTask('task2'), doTask('task3')])
}
doAllTask() // 'task1', 'task2', 'task3'
비동기! 잠깐 기다려!
const doAllTask = async () => {
await doTask('task1')
await doTask('task2')
await doTask('task3')
}
await은 Promise를 기다리기 위해 사용된다.
async 내부에서만 사용 할 수 있다.
훨씬 직관적이고 가독성이 좋다.
동기적으로 코드를 짜도 아무 상관이 없다.