Synchronous : 동기적인 처리, 요청을 받고 작업을 처리하는 동안 다른 요청을 멈춘다.
Asynchronous : 비동기적인 처리, 요청을 받으면서 작업을 처리
위 사진에서 보면 동기적인처리는 하나의 작업이 끝나야지 다음 작업을 실행하기 때문에 시간이 걸리는 반면 비동기는 하나의 작업과 동시에 다른 작업을 실행하기 때문에 시간적인 측면에서 효율적으로 활용 가능하다.
만약, 우리가 유튜브를 본다고 했을 때, 인터넷 상황이 안 좋으면 로딩이 길다. 그 말은 즉, 영상을 가져오기까지 오랜 시간이 걸린다는 것이다. 하지만 영상이 로딩 되는 동안 다른 작업을 할 수 없다면 어떨까? 매우 불편할 것이다.
유튜브 처럼 영상이 로딩 되는동안 다른 영상을 틀거나 다른 작업을 할 수 있는 것을 비동기라고 한다.
비동기 작업에서 순서를 제어하고 싶으면 어떻게 해야할까?
const printString = (string) => {
setTimeout(
() => {
console.log(string)
},
Math.floor(Math.random()*100)+1
)
}
const printAll = () => {
printString("A")
printString("B")
printString("C")
}
printAll() // What do you expect?
위 코드의 printString
함수는 랜덤한 시간을 받은 후 랜덤하게 문자열을 출력하는 함수이다. 그렇다면 그 밑에 printAll
함수를 실행하면 어떻게 될까요? 아마 무작위 순서로 A, B, C가 출력될 것 입니다.
const printString = (string, callback) => {
setTimeout(
() => {
console.log(string)
callback()
},
Math.floor(Math.random()*100)+1
)
}
const printAll = () => {
printString("A", () => {
printString("B", () => {
printString("C", () => {})
})
})
}
printAll() // now what do you expect?
그렇다면 이 함수의 결과는 어떻게 나올까요? A, B, C 는 순서대로 출력될 것 입니다. 그렇다면 왜 이 함수는 순서대로 출력 될까요. 이유는 callback
함수를 인자를 줌으로 console.log(string)
을 실행한 뒤 callback
함수를 실행 하기 때문입니다.
이 처럼 callback
을 통해서 우리는 함수의 비동기 작업의 순서를 제어 할 수 있게 된다.
//Callback error handling Design
const somethingGonnaHappen = callback => {
waitingUntilSomethingHappens()
if(isSomethingGood){
callback(null, something)
}
if(isSomethingBad){
callback(something, null)
}
}
//Usage
somethingGonnaHappen((err,data) => {
if(err){
console.log('ERR!!');
return;
}
return data;
})
callback
이 이렇게 고마운 친구지만 계속해서 사용한다면 코드가 계속 밀려들아가면서 작성 될 것이다. 이를 해결해 주는 것이 바로 promise
이다.
new Promise() <promis는 객체다>
resolve() : Go to Next Action
reject() : Handle Error
Promise
는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
//Callback -> Promise
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(
() => {
console.log(string)
resolve()
},
Math.floor(Math.random()*100) + 1
)
})
}
const printAll = () => {
printString("A")
.then(() => {
return printString("B") //메서드 체인을 위해서 리턴해줘야 한다.
})
.then(() => {
return printString("C")
})
}
printAll()
위 코드는 A, B, C를 출력하는 callback
함수를 Promise
로 나타낸 것이다. callback
에 비해서 가독성이 좋고 코드가 훨씬 깔끔해 졌다.
Promise
는 첫 함수를 실행하고 다음 실행 함수를 .then()
으로 넘겨준다. callback
은 에러 핸들링을 매번 처리해줘야 하는 것과 다르게 promise
는 .catch()
를 통해서 어디서 에러가 나도 잡아낼 수 있다.
Promise는 다음 3가지 특징을 보장한다.
.then()
을 이용하여 추가한 콜백의 경우에도 위와 같다..then()
을 여러번 사용하여 여러개의 콜백을 추가할 수 있다. 그리고 각각 순서대로 실행된다.Promise의 가장 큰 장점은 chaining
이다.
const result = async () => {
const one = await gotoCodestates();
console.log(one)
const two = await sitAndCode();
console.log(two)
const three = await eatLunch();
console.log(three)
const four = await goToBed();
console.log(four)
위 코드는 비동기적으로 실행이 되기는 하지만, 코드 자체가 동기적인 모양으로 작성이 되서 훨씬 가독성이 좋아진다.