JavaScript는 동기적 언어이다.
동기(synchronous)
JavaScript는 싱글 스레드 기반으로 동작하는 언어로 특정 코드의 실행이 완료될 때까지 기다리고 난 후 다음 코드를 수행하는 한다.
컴퓨터 발전에 따라 하나의 컴퓨터가 여러 작업을 처리하는 등의 기능이 필요하게 되었다. → 비동기식이 필요하다.(ex.유튜브, 게임 등)
비동기(asynchronous)
특정 코드의 실행이 완료될 때까지 기다리지않고 다음 코드들을 수행하는 것
JavaScript 비동기적 실행(Asynchronous execution)
아래 작업의 경우 비동기적 실행으로 작동되어야 효율적이다.
- 백그라운드 실행, 로딩 창 등의 작업
- 인터넷에서 서버로 요청을 보내고, 응답을 기다리는 작업
- 큰 용량의 파일을 로딩하는 작업
비동기 경험
타이머 관련 API
setTimeout(function, delay, arg)
: 일정 시간 후에 함수를 실행
// 예시 1 : callback를 사용하여 setTimeout 실행
// setTimeout (callback, millisecond)
setTimeout(function () {
console.log('1초 후 실행');
}, 1000);
// 123 (임의의 타이머 ID)
// 예시 2 : callback 함수를 화살표함수 형태로 사용하여 setTimeout 실행
setTimeout( ()=> {
console.log('1초 후 실행');
}, 1000);
// 17 (임의의 타이머 ID)
// 예시 3 : 함수명을 이용하여 setTimeout 실행
function timer() {
console.log('1초 후 실행');
}
let timerLet = (setTimeout(timer, 1000));
// undefined
// 1초 후 실행
// 예시 4 : 함수와 인자를 이용하여 setTimeout함수를 실행
function result (name, age) {
console.log (`이름은 ${name} 입니다.`);
console.log (`나이는 ${age}살 입니다.`);
}
let timerlet = setTimeout(result, 1000, "김코딩", "23");
// undefined
// 이름은 김코딩 입니다.
// 나이는 23살 입니다.
clearTimeout(timeoutID)
: setTimeout
타이머를 종료
const timer = setTimeout(function () {
console.log('10초 후 실행'); // console에 출력되지않음(10초 후 실행할 것을 취소했기 때문)
}, 10000);
clearTimeout(timer);
// return 값: 없음
// setTimeout이 종료됨.
setInterval(function, delay, arg)
: 일정 시간의 간격을 가지고 함수를 반복적으로 실행
// 예시 1 : callback를 사용하여 setTimeout 실행
// setTimeout (callback, millisecond)
setInterval(function () {
console.log('1초마다 실행');
}, 1000);
// 123 (임의의 타이머 ID)
clearInterval(intervalID)
: setInterval
타이머를 종료
const timer = setInterval(function () {
console.log('1초마다 실행');
}, 1000);
clearInterval(timer);
// return 값: 없음
// setInterval이 종료됨.
clearTimeout 이 setInterval 를 종료할 수 있고, clearInterval 이 setTimeout 를 종료할 수 있다.
단, 명확성과 혼란 방지를 위하여 아래와 같이 사용할 것
setTimeout은 clearTimeout과 사용
setInterval은 clearInterval과 사용
비동기 코드는 실행할 때마다 순서가 바뀜
예시
const printString = (string) => {
setTimeout(function () {
console.log(string);
}, Math.floor(Math.random() * 100) + 1);
};
const printAll = () => {
printString('A');
printString('B');
printString('C');
};
printAll();
console.log(`아래와 같이 비동기 코드는 순서를 보장하지 않습니다!`);
// 터미널
아래와 같이 비동기 코드는 순서를 보장하지 않습니다!
C
B
A
비동기 코드 제어하기
1. Callback 함수 사용
const printString = (string, callback) => {
setTimeout(function () {
console.log(string);
callback();
}, Math.floor(Math.random() * 100) + 1);
};
const printAll = () => {
printString('A', () => {
printString('B', () => {
printString('C', () => {});
});
});
};
// 터미널
아래와 같이 Callback 함수를 통해 비동기 코드의 순서를 제어할 수 있습니다!
A
B
C
2. Promise, asyns/await
Callback 함수로 제어할 수 있지만 코드가 길어지고 복잡해진다.
가독성이 낮아지는 Callback Hell이 발생하는 단점이 있다.
Promise는 Callback Hell을 방지하며, 비동기 코드를 제어할 수 있다.
Promise
new Promise : Promise는 class이기 때문에 new 키워드로 Promise 객체 생성
Promise
는 비동기 처리를 수행할 콜백 함수(executor
)를 인수로 전달받는데 이 콜백 함수는 resolve
, reject
함수를 인수로 전달받음
let promise = new Promise((resolve, reject) => {
resolve(value);
reject(error);
})
Promise 객체의 내부 프로퍼티 State : 기본 상태 pending
(대기), 성공 fulfilled
(이행), 에러 rejected
(거부) Result : 처음 undefined
, 성공 value
, 에러 error
then, catch, finally
let promise = new Promise(function(resolve, reject) {
resolve("성공");
});
promise
.then(value => {
console.log(value);
// "성공"
})
.catch(error => {
console.log(error);
})
.finally(() => {
console.log("성공이든 실패든 작동!");
// "성공이든 실패든 작동!"
})
Promise chaining : 비동기 작업을 순차적으로 진행할 때 사용
// 예시 1
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
console.log(string);
}, Math.floor(Math.random() * 100) + 1);
});
};
const printAll = () => {
printString('A')
.then(() => {
return printString('B');
})
.then(() => {
return printString('C');
});
};
printAll();
console.log(
`아래와 같이 Promise를 통해 비동기 코드의 순서를 제어할 수 있습니다!`
);
// 출력
아래와 같이 Promise를 통해 비동기 코드의 순서를 제어할 수 있습니다!
A
B
C
// 예시 2
let promise = new Promise(function (resolve, reject) {
resolve('성공');
// reject("실패");
});
promise
.then((value) => {
console.log(value);
return '성공';
})
.then((value) => {
console.log(value);
return '성공';
})
.then((value) => {
console.log(value);
return '성공';
})
.catch((error) => {
console.log(error);
return '실패';
})
.finally(() => {
console.log('성공이든 실패든 작동!');
});
// 출력
성공
성공
성공
성공이든 실패든 작동!
Promise.all() : 여러 개의 비동기 작업을 동시에 처리할 때 (Promise chaining 보다 처리 속도 빨라짐)
// 기존
const result = [];
promiseOne()
.then(value => {
result.push(value);
return promiseTwo();
})
.then(value => {
result.push(value);
return promiseThree();
})
.then(value => {
result.push(value);
console.log(result);
// ['1초', '2초', '3초']
})
// promise.all
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
.then((value) => console.log(value))
// ['1초', '2초', '3초']
.catch((err) => console.log(err));
// promise.all은 Promise 중 하나라도 에러 발생 시 나머지 Promise의 state와 상관없이 즉시 종료
Promise.all([
new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러1'))), 1000),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러2'))), 2000),
new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러3'))), 3000),
])
.then((value) => console.log(value))
.catch((err) => console.log(err));
// Error: 에러1
Async/Await : Promise
코드를 간결하게 작성
// 함수 선언식
async function funcDeclarations() {
await 작성하고자 하는 코드
...
}
// 함수 표현식
const funcExpression = async function () {
await 작성하고자 하는 코드
...
}
// 화살표 함수
const ArrowFunc = async () => {
await 작성하고자 하는 코드
...
}
// 예시
const printString = (string) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
console.log(string);
}, Math.floor(Math.random() * 100) + 1);
});
};
const printAll = async () => {
await printString('A');
await printString('B');
await printString('C');
};
printAll();
console.log(
`Async/Await을 통해 Promise를 간결한 코드로 작성할 수 있게 되었습니다.`
);
'JavaScript' 카테고리의 다른 글
redux (0) | 2023.04.24 |
---|---|
[JavaScript] 함수선언식, 함수표현식, 화살표함수 (0) | 2023.03.26 |
[JavaScript] 배열, 배열 메서드(method) (0) | 2023.03.25 |
[JavaScript] 타이머 API (0) | 2023.03.19 |
[JavaScript] 배열 고차 함수 (0) | 2023.03.17 |
댓글