티스토리 뷰
비동기 프로그래밍으로 발생하는 콜백지옥을 해결하는 방법으로 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 객체를 받게 된다는 뜻으로 사용하였습니다.
* 참고 - 리턴 값 확인하기
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를 실행하는 함수입니다.
참고
'JavaScript' 카테고리의 다른 글
| [자바스크립트] ES6(ECMA Script6) - export, import (6) | 2017.02.13 |
|---|---|
| [자바스크립트] 정규식(Regular Expressions) (10) | 2017.02.08 |
| [자바스크립트] ES6(ECMA Script 6) - for ... of 문 (0) | 2017.01.20 |
| [자바스크립트] ES6(ECMA Script 6) - 화살표 함수(Arrow function) (3) | 2017.01.19 |
| [자바스크립트] ES6(ECMA Script 6) - 구조분해 할당(Destructuring assignment) (7) | 2017.01.18 |
