동기(synchronous) 와 비동기 (asynchronous)
자바스크립트는 동기적인 것이다. 바로 hoisting 된 이후부터 코드가 나타나는 순서에 맞춰서 하나하나씩 동기적으로 실행된다.
- hoisting : var 변수와 또는 function declaration 같은 것들이 선언들이 제일 위로 올라가는 것
동기
console.log("1");
console.log("2");
console.log("3");
이렇게 작성된 순서에 맞게 console.log를 찍으면 1,2,3 이렇게 차례대로 나오는 것을 볼 수가 있다.
비동기 asynchronous
정해진 순서에 맞지 않고, 언제 실행될 지 모르는 것이 비동기이다.
console.log("1");
setTimeout()
console.log("2");
console.log("3");
이렇게 브라우저 api의 setTimeout() 과 같이 지정된 시간이 경과하면 콜백함수를 호출해준다.
이렇게 언제 실행될 지 모르는 것이 비동기 이다.
callback 함수
전달해준 함수를 나중에 불러주는 것이다.
console.log("1");
setTimeout(function () {
console.log("2");
}, 1000);
console.log("3");
이렇게 되면, 1000이 1초라는 뜻이고 1초가 지난다음 2를 콘솔에 보여준다는 뜻이니까.
미리 코딩을 해놔도 1초 있다가 2가 출력되므로 1, 3, 2로 출력이 될 것이다.
동기 callback
console.log("1");
setTimeout(() => console.log("2"), 1000);
console.log("3");
function printImmediately(print) {
print();
}
printImmediately(() => console.log("hello"));
동기 callback 은 바로 호출이 되는 callback 함수이다.
이렇게 1,3이 호출되고 함수의 선언은 우리가 알다시피 hoisting 된다.
function printImmediately(print) {
print();
}
console.log("1");
setTimeout(() => console.log("2"), 1000);
console.log("3");
printImmediately(() => console.log("hello"));
그러므로 이런 상황이 될 것이다. 그렇다면, 이 코드의 순서는
- 함수가 선언되고
- 1번이 콘솔출력되고
- setTimeout 으로 브라우저에게 요청한다음
- 3번이 콘솔출력되고
- printImmediately로 함수 호출해서 콘솔에 hello를 출력하고
- 1초가 지난 후 2번이 콘솔출력
이런 순서일 것이다.
이것은 바로 출력이 되는 동기성 callback 이다.
비동기 callback
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(() => console.log("async callback"), 2000);
이렇게 setTimeout으로 async를 걸어주면, 비동기 callback 이다. 이것은 2000ms 즉 2초를 기다렸다가 브라우저에 뜨도록 할 것이다.
콜백 지옥 예시
class userStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if (
(id === "ellie" && password === "dream") ||
(id === "coder" && password === "coding")
) {
onSuccess(id);
} else {
onError(new Error("not found"));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === "ellie") {
onSuccess({ name: "ellie", role: "admin" })
} else {
onError(new Error("no access"));
}
}, 1000);
}
}
const id = prompt("id please");
const password = prompt("password please");
const storage = new userStorage();
storage.loginUser(
id,
password,
(id) =>
storage.getRoles(
id,
(userRole) => {
console.log(`hi ${userRole.name}, your role is ${userRole.role}`);
},
(onError) => {
console.log(error);
}
),
(error) => {
console.log(error);
}
);
이렇게 콜백 지옥 관련에서 코드를 짜 보았다.
콜백 안에서 무언가 다른 것을 호출하고 전달하고 그 안에서 만약 다른 것을 호출하고 전달전달 하면
이것이 바로 콜백 지옥이다.
콜백 지옥의 문제점
- 읽기가 거북하다 (가독성이 떨어짐)
- 어느곳에서 연결되어있는지 한눈에 가늠하기 어렵다.
- 오류가 발생하거나 디버깅을 해야하는 경우에도 굉장히 어렵다 (유지보수가 어려움)
'JavaScript' 카테고리의 다른 글
javascript 비동기 프로그래밍 - async await / 유용한 promise APIs (0) | 2022.09.17 |
---|---|
javascript 비동기 프로그래밍 - Promise 개념, 활용 (1) | 2022.09.17 |
javascript JSON 개념 정리와 활용 방법 및 유용한 사이트 공유 (0) | 2022.09.16 |
javascript 유용한 10가지 배열 함수들. Array APIs 총정리 (0) | 2022.09.16 |
javascript 배열 (0) | 2022.09.15 |