앞서 살펴본 약속(Promise)에 대해서 자세히 알아보자.
- Promise.all(): Promise의 배열을 매개변수로 삼고, 배열의 모든 Promise가 fulfil일 때만 새로운 fulfil Promise 오브젝트를 반환
- .finally(): Promise의 결과가 fulfilled 인지 rejected인지 관계 없이 Promise가 완료된 후 최종 코드 블럭을 실행하려는 경우 사용
이벤트 리스너와 다른점
- 한번에 성공/실패 중 하나의 결과값을 가진다. 하나의 요청에 두 번 성공하거나 실패할 수 없다.
또한 이미 성공한 작업이 다시 실패로 돌아갈 수 없고 실패한 작업이 성공으로 돌아갈 수 없다.
Promise() 생성자 사용
- 주로 Promise기반이 아닌 구식 비동기 API코드를 Promise기반 코드로 만들고 싶을 경우 사용.
- resolve(): Promise가 resolve상태일 때 전달할 값을 지정할 수 있다.
- reject(): Promise가 reject상태일 때 전달할 값을 지정할 수 있다.
async 키워드
- 함수 앞에 async 키워드를 사용하면 반환받는 값은 Promise 객체가 된다.(상태:fulfil) 즉, 해당 함수를 Promise로 바꾼다.
- async 키워드를 class/object의 메서드에 사용하여 Promise 객체를 반환하게 만들 수 있다.
function hello() {
return "Hello"
}
console.log(hello());
async function asyncHello() {
return "Hello"
}
console.log(asyncHello());
await 키워드
- 웹 API를 포함하여 Promise를 반환하는 함수를 호출할 때 사용할 수 있다.
- JavaScript 런타임이 키워드가 선언된 라인에서 비동기 코드를 일시 중지하여 비동기 함수 호출이 결과를 반환할 때 까지 기다리게 하며 외부의 다른 동기 코드는 실행될 수 있도록 한다. 작업이 완료되면 선언된 라인 아래의 코드는 계속 이어져서 실행된다.
- async function 안에서만 사용할 수 있다.
- async/await는 Promise의 상위에 만들어져 있기 때문에 Promise의 모든 기능을 사용할 수 있다.
- 동기화 코드처럼 보이게하여 가독성이 올라간다.
async function asyncHello() {
return greeting = await Promise.resolve("Hello");
};
asyncHello().then(alert);
async/await 주의점
- async/await는 어떤 면에서는 정말로 동기적으로 행동한다.
-> 함수 블럭에 여러 개의 await 키워드를 사용하면 Promise가 fulfilled되기 전까지 다음 await을 차단한다.(그 동안 다른 태스크는 계속 실행이 되지만 정의한 함수 내에서는 동기적으로 작동)
이는 바로 이어지는 수 많은 Promise에 의해 느려질 수 있다는 것을 의미한다.
(각 await는 이전의 작업이 끝날 때까지 기다리기 때문인데 Promise 체이닝과 혼동하지 말자)
function timeoutPromise(interval) {
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve("done");
}, interval);
});
};
async function timeTest() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}
let startTime = Date.now();
timeTest().then(() => {
let finishTime = Date.now();
let timeTaken = finishTime - startTime;
alert("Time taken in milliseconds: " + timeTaken);
})
timeTest의 동작은 3초마다 종료되며 총 9초의 시간이 걸리게 된다.
하지만 아래의 형태로 먼저 비동기 함수는 자유롭게 실행되도록 두고 변수가 사용가능 할 때 꺼내쓰도록 리팩토링 하면 총 시간이 3초로 줄어들게 된다.
async function timeTest() {
const timeoutPromise1 = timeoutPromise(3000);
const timeoutPromise2 = timeoutPromise(3000);
const timeoutPromise3 = timeoutPromise(3000);
await timeoutPromise1;
await timeoutPromise2;
await timeoutPromise3;
}
해당 문법을 사용하고 성능이 떨어지기 시작하면 위의 상황을 의심해봐야 한다.
[참고자료]
MDN WEB DOCS - Graceful asynchronous programming with Promises
MDN WEB DOCS - Making asynchronous programming easier with async and await
'JavaScript > 기본' 카테고리의 다른 글
자바스크립트 비동기(Javascript Asynchronous) 처리 이해 - 콜백(Callback), 약속(Promise) (0) | 2021.05.03 |
---|---|
자바스크립트(Javascript) - 동기(Synchronous), 비동기(Asynchronous) 방식 이해 (0) | 2021.05.03 |
자바스크립트(Javascript) - 객체(Object)와 프로토타입(Prototype) (0) | 2021.04.27 |