동기와 비동기차이
⦁ 동기적(Synchronous)
어떤 작업을 요청했을 때 그 작업이 종료될때 까지 기다린 후 다음 작업을 수행하는 방식
⦁ 비동기적(Asynchronous)
어떤 작업을 요청했을 때 그 작업이 종료될때 까지 기다리지 않고 다른 작업을 하고 있다가, 요청했던 작업이 종료되면 그에 대한 추가 작업을 수행하는 방식
자바스크립트는 동기적인 것입니다.
*호이스팅된 이후부터 코드가 우리가 작성한 순서에 맞춰서 하나하나씩 동기적으로 실행된다는 말입니다.
*호이스팅: var변수, function선언들이 자동적으로 제일 위로 올라가는 것
console.log('1');
console.log('2');
console.log('3');
동기적(Synchronous)은 위 console.log와 같이 1,2,3 순서대로 실행됩니다.
반대로 비동기적(Asynchronous)는 언제 코드가 실행될지 예측할수없는 것입니다.
좋은 예로는 setTimeout이라는 web API가 있는데 이것은 브라우저에서 제공되어지는 API로
우리가 지정한 시간이 지나면 우리가 전달한 함수인 *콜백함수를 호출하는 것입니다.
console.log('1');
setTimeout(function (){
console.log('2');
}, 1000);
console.log('3');
//위와 동일한 코드
console.log("1");
setTimeout(() => console.log("2"), 1000); //화살표함수사용
console.log("3");
//setTimeout 안에 함수는 함수임을 일일이 표기하지않고
//arrow function을 이용해 짧게 코드를 작성해도 됩니다.
setTimeout 함수 안에 1000은 1초를 의미합니다.
위 코드를 실행하면 setTimeout은 브라우저요청을 보내고, 1초 뒤에 전달한 함수인 콜백함수를 실행합니다.
그럼 콜백은 항상 비동기에서만 사용하는가?
아닙니다. 콜백도 두가지의 경우로 나뉘어집니다.
즉각적으로 실행되는 Synchronous callback과
언제 실행될지 예측할수없는 Asynchronous callback 으로 나누어 생각할수있습니다.
[Synchronous callback 예제]
console.log("1");
setTimeout(() => console.log("2"), 1000);
console.log("3");
function printImmediately(print) {
print();
}
printImmediately(() => console.log("hello"));
// printImmediately는 콜백함수를 받아서 바로 실행
// hello는 바로 실행되지만 2는 1초 후에 실행
[Asynchronous callback 예제]
console.log('1');
setTimeout(() => console.log('2'), 1000); //1초뒤 실행
console.log('3');
function printImmediately(print){
print();
}
printImmediately(()=> console.log('hello'));
function printWithDelay(print, timeout){
setTimeout(print, timeout);
}
printWithDelay(() => console.log('async callback'), 2000);
// printWithDelay함수는 콜백함수를 2초후에 실행하게 됩니다.
콜백지옥 조심!
콜백함수는 유용하게 쓰일수도있지만
콜백지옥이 될 수있다는 점도 유의해야 합니다.
[콜백지옥 예시]
class UserStorage{
loginUser(id, password, onSuccess, onError){
setTimeout(() =>{
if(
(id === 'seul' && password === '123') ||
(id === 'kim' && password === '456')
) {
onSuccess(id);
} else{
onError(new Error('error'));
}
}, 2000);
}
getRoles(user, onSuccess, onError){
setTimeout(()=> {
if (user === 'seul') {
onSuccess({name: 'seul', role: 'admin'});
} else {
onError(new Error('error'));
}
}, 1000);
}
};
const userStorage = new UserStorage();
const id = prompt('아이디를 입력해 주세요!');
const password = prompt('비밀번호를 입력해 주세요!!');
userStorage.loginUser(
id,
password,
user => {
userStorage.getRoles(
user,
userWithRole => {
alert(`hello ${userWithRole.name}, you have a ${userWithRole.role} role`)
},
error => {
console.log('에러2')
}
);
},
error => {console.log('에러1')}
);
콜백안에서 전달하고.. 전달하고...체인이 길어지면 문제가 생깁니다.
가독성도 떨어지고, 디버깅 하기도 어렵고, 유지보수 하기가 어려워집니다.
이러한 콜백지옥은 promise 를 이용해 탈출 할 수 있습니다.
아래는 promise로 수정한 코드입니다.
class UserStorage{
loginUser(id, password){
return new Promise((resolve, reject) => {
setTimeout(() =>{
if(
(id === 'seul' && password === '123') ||
(id === 'kim' && password === '456')
) {
resolve(id);
} else{
reject(new Error('에러1'));
}
}, 2000);
})
}
getRoles(user){
return new Promise((resolve, reject) => {
setTimeout(()=> {
if (user === 'seul') {
resolve({name: 'seul', role: 'admin'});
} else {
reject(new Error('에러2'));
}
}, 1000);
})
}
};
const userStorage = new UserStorage();
const id = prompt('아이디를 입력해 주세요!');
const password = prompt('비밀번호를 입력해 주세요!!');
userStorage.loginUser(id, password)
.then(userStorage.getRoles)
// .then(user => userStorage.getRoles(user)); 인자가 똑같으니 생략 가능하다.
.then(user => alert(`hello ${user.name}, you have a ${user.role} role`))
.catch(console.log);
- 1) userStorage에서 로그인을 한다.
- 2) 로그인이 성공하면 user가 전달되므로 전달된 user를 이용해서 getRoles,를 호출한다.
- 3) getRoles 까지 성공적으로 수행 된다면 최종적으로 받아온 user를 이용해서 alert창을 나타낸다.
모두 성공적으로 마쳤을 때 결과와, 도중에 실패했을 때▼
마지막행의 .catch(console.log); 를 작성하지 않고 에러가 발생했을 때 ▼
promise 설명정리 링크 :
https://rebornbb.tistory.com/entry/JS-Promise-%EA%B0%9C%EB%85%90%EA%B3%BC-%ED%99%9C%EC%9A%A9
정리 출처 : 드림코딩
https://www.youtube.com/watch?v=s1vpVCrT8f4&list=WL&index=2
'STUDY > JavaScript' 카테고리의 다른 글
[JS] 음악 및 오디오 플레이어 Javascript 라이브러리 (0) | 2023.03.09 |
---|---|
[JS] Promise에 대해 알아보자 (0) | 2023.02.01 |
[JS] 자바스크립트 내장함수 (0) | 2023.01.19 |
[JS] 브라우저 객체 모델 (0) | 2023.01.16 |
[JS] 자바스크립트 내장 객체 (0) | 2023.01.16 |