sitelink1 | https://beomy.tistory.com/45 |
---|---|
sitelink2 | |
sitelink3 | |
sitelink4 | |
extra_vars4 | |
extra_vars5 | |
extra_vars6 |
비동기 프로그래밍으로 발생하는 콜백지옥을 해결하는 방법으로 ES6에서 추가된 Promise를 사용하는 방법이 있습니다. ([자바스크립트] 비동기프로그래밍 - 콜백함수(Callback function) 참고) 이번 포스트에서는 비동기 프로그래밍을 처리할 수 있는 방법으로 async
와 await
에 대해 이야기 하려 합니다.
1. 문법
async function name([param[, param[, ... param]]]) {
statements
}
- name: 함수 이름
- param: 함수에 전달되는 인자들의 이름
- statements: 함수 본문
- 리턴 값: async 함수의
return
값으로resolve
된Promise
객체 혹은 async 함수에서 예외가 발생하였다면 발생 된 예외로reject
된Promise
객체
async 함수를 사용하는 방법은 기본 함수를 생성하는 것과 큰 차이가 없습니다. 그렇기 때문에 Promise
를 이용하는 것보다 async
, await
를 사용할 때 코드가 더 간결해 질 수 있습니다. async 함수의 리턴 값은 resolve
된 Promise
객체, 혹은 reject
된 Promise
객체를 암묵적으로 리턴합니다. 암묵적으로 리턴한다는 말은, new Promise
를 사용하여 Promise
객체를 리턴하지 않아도 async 함수의 리턴 값으로 Promise
객체를 받게 된다는 뜻으로 사용하였습니다.
* 참고 - 리턴 값 확인하기
async 함수 안에서 리턴 한 값은 resolve 된 Promise 객체로 리턴 되어 집니다.
async 함수 안에서 발생한 예외는 reject 된 Promise 객체로 리턴 되어 집니다.
2. 데모
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
var result = await resolveAfter2Seconds();
console.log(result);
// expected output: 'resolved'
}
asyncCall();
3. 설명
async 함수에서는 await
를 사용할 수 있습니다. await
는 async 함수에서만 사용 가능합니다. 일반 함수에서 await
를 사용하게 되면 syntax error가 발생됩니다.
await
는 Promise
와 함께 사용되어야 합니다. await
를 사용하면 Promise
가 종료 될 때까지 함수 실행이 일시 정지 됩니다. 그후 Promise
가 종료 되면 함수 실행이 다시 진행 됩니다. await
사용하면 Promise
에서 resolve
된 값을 반환 받게 됩니다. await
의 Promise
가 reject
되면, 예외가 발생됩니다.
function awaitFunction() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('success'), 1000);
// setTimeout(() => reject('fail'), 1000);
});
}
async function asyncFunction() {
try {
const msg = await awaitFunction();
console.log(msg); // awaitFunction에서 resolve가 호출 될 때 resolve의 인자값 'success'
} catch (e) {
console.log(e); // awaitFunction에서 reject가 호출 될 때 reject의 인자값 'fail'
}
}
asyncFunction();
Promise
의 사용 방법을 단순히 하기 위해서(Promise
의 콜백 함수 동작을 단순히 보이기 위해서) async
와 await
가 사용됩니다.
var resolveAfter2Seconds = function() {
console.log("starting slow promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(20);
console.log("slow promise is done");
}, 2000);
});
};
var resolveAfter1Second = function() {
console.log("starting fast promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(10);
console.log("fast promise is done");
}, 1000);
});
};
var sequentialStart = async function() {
console.log("==SEQUENTIAL START==");
// If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
const slow = await resolveAfter2Seconds();
const fast = await resolveAfter1Second();
console.log(slow);
console.log(fast);
}
var concurrentStart = async function() {
console.log("==CONCURRENT START with await==");
const slow = resolveAfter2Seconds(); // starts timer immediately
const fast = resolveAfter1Second();
console.log(await slow);
console.log(await fast); // waits for slow to finish, even though fast is already done!
}
var stillSerial = function() {
console.log("==CONCURRENT START with Promise.all==");
Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then(([slow, fast]) => {
console.log(slow);
console.log(fast);
});
}
var parallel = function() {
console.log("==PARALLEL with Promise.then==");
resolveAfter2Seconds().then((message)=>console.log(message)); // in this case could be simply written as console.log(resolveAfter2Seconds());
resolveAfter1Second().then((message)=>console.log(message));
}
sequentialStart(); // takes 2+1 seconds in total
// wait above to finish
setTimeout(concurrentStart, 4000); // takes 2 seconds in total
// wait again
setTimeout(stillSerial, 7000); // same as before
// wait again
setTimeout(parallel, 10000); // trully parallel
위의 예제는 MDN에 나와 있는 async
, await
예제입니다. 코드가 길고 복잡해 보이지만 뜯어 보면 어렵지 않은 코드입니다.
resolveAfter2Seconds
: 2초후Promise.resolve
로 20을 내보내는 함수입니다.resolveAfter1Second
: 1초후Promise.resolve
로 10을 내보내는 함수입니다.sequentialStart
:resolveAfter2Seconds
와resolveAfter1Second
를await
를 이용하여 순차적으로 결과를 받는 함수입니다. 순차적으로 결과를 받기 때문에, 2초(resolveAfter2Seconds
) + 1초(resolveAfter1Second
) = 3초 후console.log
출력 값을 확인 할 수 있습니다.concurrentStart
:resolveAfter2Seconds
와resolveAfter1Second
를 동시(엄밀히 말하면 동시는 아니지만..) 실행하고 그 후await
로 결과를 받는 함수입니다. 동시에 함수들이 실행 되기 때문에 가장 마지막으로 종료 되는 2초(resolveAfter2Seconds
) 후console.log
출력 값을 확인 할 수 있습니다.stillSerial
:Promise.all
을 사용하여concurrentStart
와 동일한 기능을 구현한 함수입니다.parallel
: 병렬로resolveAfter2Seconds
와resolveAfter1Second
를 실행하는 함수입니다.
참고
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
11 | data library js 정의 및 사용 (exprt & import) | 황제낙엽 | 2023.02.16 | 48 |
10 | 객체 디스트럭처링 (Destructuring assignment) | 황제낙엽 | 2023.01.07 | 45 |
9 |
자바스크립트 ES6 모듈 내보내기/불러오기 (import/export)
![]() | 황제낙엽 | 2023.01.07 | 49 |
8 | for 구문을 while 처럼 조회 | 황제낙엽 | 2021.03.07 | 475 |
7 | [ES6] Rest parameters | 황제낙엽 | 2021.03.07 | 292 |
6 | [ES6] Default parameters | 황제낙엽 | 2021.03.07 | 67 |
5 | [ES6] “콜백 지옥 (callback hell)”을 제거하는 제너레이터(Generator) | 황제낙엽 | 2021.02.18 | 81 |
» |
ES8(ECMA Script 8) - async, await
![]() | 황제낙엽 | 2020.08.26 | 133 |
3 | [ES6] ES 2015 (ES 6) 이후 추가된 기능들 정리 | 황제낙엽 | 2020.08.03 | 66 |
2 | 브라우저별 Javascript ECMA Script 지원 스펙 레퍼런스 링크 | 황제낙엽 | 2019.09.16 | 312 |
1 |
[ES6] let, const 블록 레벨 스코프
![]() | 황제낙엽 | 2018.04.11 | 174 |