// ES7
async function foo() {
await bar();
...
담 작업들!!
...
}
// ES5 complied
let foo = (() => {
var _ref = _asyncToGenerator(function*() {
yield bar();
});
return function foo() {
return _ref.apply(this, arguments);
};
})();
function _asyncToGenerator(fn) {
// generator 함수를 받아온다
return function() {
var gen = fn.apply(this, arguments);
// .apply로 generator 실행
// iterator 객체를 gen 안에 넣어서 클로저로 저장해둔다
return new Promise(function(resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
// next() 호출, iterator 객체 소환
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) { // true 면 종료
resolve(value);
} else {
return Promise.resolve(value).then(
function(value) {
step("next", value);
// 재귀함수를 통해 반복실행
},
function(err) {
step("throw", err);
}
);
}
}
return step("next");
});
};
}
async 키워드를 generator 로 바꾸고 await 키워드는 yield 로 바꿨다
→ 실제 쓰는 상 await가 next 로 return 됨은 아님 유의
→ yield는 동기적인 모습을 바꿔주는 용도로 쓰인다
→ 비동기 로직이 완료(Promise.resolve
) 될 때마다 적절하게 next()
를 호출되고 다음 작업이 실행된다
foo()
는 내부에서 await
를 만나면 bar()
실행 후 Promise
채우고 제어권을 foo() 밖으로 넘긴다bar()
내부의 Promise
가 resolve
되면 foo()
의 제너레이터 next()
가 실행되서 foo()
의 await
이후의 라인으로 다시 루틴이 시작된다function resolveAfter4Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 4000);
});
}
async function asyncCall() {
console.log('calling');
const result = await resolveAfter4Seconds();
console.log(result);
console.log('1');
console.log('2');
// expected output: "resolved"
}
asyncCall();
console.log('3');
// calling 3 resolved 1 2 순서로 출력