비동기처리란?
특정 코드의 연산이 끝날 때 까지 코드의 실행을 멈추지 않고, 순차적으로 다음 코드를 먼저 실행하는 자바스크립트의 특성(싱글스레드, 콜스택). 즉, 요청을 보낸 후 응답에 관계없이 다음 동작을 실행한다.
동기와 비동기의 차이점
- 동기(sync): 요청을 보낸 후 해당 응답을 받아야 다음 동작을 실행한다.
- 비동기(async: 요청을 보낸 후 응답에 관계없이 다음 동작을 실행한다.
비동기 처리를 위해서 사용하는 메소드중 대표적인 setTimeout()이 있다. Web API의 한 종류로 코드를 바로 실행하지 않고, 지정한 시간만큼 기다렸다가 로직을 실행한다.
//5초후에 console.log를 띄움
setTimeout( () => {
console.log('this is timer');
}, 5000);
console.log('this is watch');
비동기 처리를 알기 전까진 출력의 순서는 다음과 같다고 생각했었다.
- 5초뒤에 this is timer 출력
- this is watch 출력
setTimeout()은 비동기 방식으로 실행되기 때문에 코드를 수행할 때, setTimeout()을 실행하고, 두번째 console.log('this is watch')를 실행한다. 그리고 5초뒤에 'this is timer'를 띄우게된다. 실제 순서는 다음과 같다.
- this is watch 출력
- 5초뒤에 this is timer 출력
callback함수로 비동기 처리
콜백함수는 파라미터(parameter)로 함수를 전달받아 함수 내부에서 실행하는 함수이다.
const printString = (string, callback) => {
setTimeout(
() => {
console.log(string)
callback()
},
Math.floor(Math.random() * 1000) + 1
)
}
const printAll = () => {
printString("A", () => {
printString("B", () => {
printString("C", () => {})
})
})
}
printAll()
위 코드를 해석하면 다음과 같다.
setTimeout() Web API를 통해 각각의 콜백함수는 n초의 시간을 갖게된다.
printString("A", callback() = 306ms
printString("B", callback() = 158ms
printString("C", callback(){?} = 91ms
printAll()을 통해 순서대로 결과를 반환한다.
가장 먼저 콜백함수 printString*("A", () )가 실행되고, 순서대로 "B", "C"가 실행된다. 콜백함수의 제일 마지막 까지 도달했으면 다시 처음 콜백 함수부터 N초 후에 결과를 반환한다.(ex. n초 후에 A, n초 후에 B)
306ms 후 A
158ms 후 B
91ms 후 C
비동기 에러 처리
자바스크립트에서 콜백을 사용할 때, 예외처리가 어려워지기 때문에 오류 우선 콜백이라는 패턴이 생겼다.
아래의 코드는 비슷한 표현의 예제로 작성되었다.
const funcName = callback() => {
//만약 상태가 이상하거나 에러난 경우
if(에러가 났다!){
callback(에러발생!, null)
}else {
callback(null, 정상적으로 잘됨)
}
}
<funcName>((err, data) => {
if (err) {
console.log("에러가 났다");
return <>;
}
return data
})
node.js를 이용한 방법
const fs = require('fs');
const path = require('path');
const firstDir = path.join(__dirname, 'directori')
let options = {
encoding: 'utf8',
flag: 'r'
}
fs.readFile(fileDir, options, (err, data) => {
if(err){
callback(err, null);
} else {
callback(null, data);
}
콜백 지옥(Callback hell)
비동기 프로그래밍에서 실행 순서를 신경쓰며 코딩을 해야한다. 아래와 같이 콜백지옥에 빠질 수 있기 때문이다.
step1(function (value1) {
step2(function (value2) {
step3(function (value3) {
step4(function (value4) {
step5(function (value5) {
step6(function (value6) {
// Do something with value6
});
});
});
});
});
});
대문자 알파벳을 출력하기위해 여러개의 콜백함수를 중첩해서 사용 하게 되는데, 요구하는 작업이 늘어날수록 더욱 더 복잡하고 가독성이 떨어지는 코드가 된다. 그래서 가독성을 높혀주기 위해 콜백함수를 지정해 주는 것이 좋다.
step1(afterStep1);
const afterStep1 = (value1) => {
step2(afterStep2);
}
const afterStep2 = (value2) => {
step3(afterStep3);
}
const afterStep2(value2) => {
step3(afterStep3);
}
const afterStep2(value2) => {
step3(afterStep3);
}
.
.
.
.
위와 같이 기명 함수로 인자를 넘기게 되면 콜백지옥은 어느정도 해결할 수 있다. 또 다른 콜백 지옥을 해결할 방식으로는
Promise와 async & await 방식이 있다.
'FE BE 개발 메모장 > Javascript' 카테고리의 다른 글
async & await (0) | 2021.02.02 |
---|---|
Promise (0) | 2021.02.01 |
자바스크립트 Prototype과 Instance (0) | 2021.01.15 |
객체(Object)와 객체를 생성하는 방법. (0) | 2021.01.14 |
함수 메소드(call, apply, bind) (0) | 2021.01.14 |