synchronous : 동시에 일어나는
a + synchronous = async : 동시에 일어나지 않는
비동기적 요소를 동기적으로 바꾸려는 이유는
순서를 보장할 수 없으니 순서보장이 필요한 로직에서 순서를 보장 받기 위해서 입니다.
Promise는 비동기 처리가 끝나면 알려달라는 '약속'입니다. new 연산자로 호출하고 Promise의 인자로 넘어가는 콜백은 바로 실행됩니다.
그 내부의 resolve(또는 reject) 함수를 호출하는 구문이 있을 경우 resolve(또는 reject) 둘 중 하나가 실행되기 전까지는 다음(then), 오류(catch)로 넘어가지 않습니다.
따라서, 비동기작업이 완료될 때 비로소 resolve(해결하다), reject(거부하다)를 호출합니다.
new Promise(function (resolve) {
setTimeout(function () {
var name = "에스프레소";
console.log(name);
resolve(name);
}, 500);
})
.then(function (prevName) {
// 안에서도 새롭게 promise를 만듬
return new Promise(function (resolve) {
setTimeout(function () {
var name = prevName + ", 아메리카노";
console.log(name);
resolve(name);
}, 500);
});
})
.then(function (prevName) {
return new Promise(function (resolve) {
setTimeout(function () {
var name = prevName + ", 카페모카";
console.log(name);
resolve(name);
}, 500);
});
})
.then(function (prevName) {
return new Promise(function (resolve) {
setTimeout(function () {
var name = prevName + ", 카페라떼";
console.log(name);
resolve(name);
}, 500);
});
});
// 리팩토링 : 위 예제의 반복부분을 함수화 한 코드
var addCoffee = function (name) {
return function (prevName) {
return new Promise(function (resolve) {
setTimeout(function () {
var newName = prevName ? prevName + ", " + name : name;
console.log(newName);
resolve(newName);
}, 500);
});
};
};
addCoffee("에스프레소")()
.then(addCoffee("아메리카노"))
.then(addCoffee("카페모카"))
.then(addCoffee("카페라떼"));
*가 붙은 함수(function*)가 제너레이터 함수입니다. 제너레이터 함수는 실행 시, Iterator 객체를 반환합니다.
이터러블 객체(Iterable : 반복될 수 있는, 반복할 수 있는)
iterator 객체는 next라는 메서드를 가지고 있고 next 메서드로 순환 할 수 있는 객체입니다.
next 메서드 호출 시, Generator 함수 내부에서 yield(양보하다, 미루다) → stop을 실행합니다. 이후 다시 next 메서드를 호출하면 멈췄던 부분에서 그 다음의 yield까지 실행 후 stop합니다.
즉, 비동기 작업이 완료되는 시점마다 next 메서드를 호출해주면 Generator 함수 내부소스가 위에서 아래로 순차적으로 진행됩니다.
// 제너레이터 함수 안에서 쓸 addCoffee 함수 선언
var addCoffee = function (prevName, name) {
setTimeout(function () {
coffeeMaker.next(prevName ? prevName + ", " + name : name);
}, 500);
};
// 제너레이터 함수 선언
// yield 키워드로 순서 제어
var coffeeGenerator = function* () {
// yield addCoffee : addCoffee 함수 안의 next를 만날때까지 수행
var espresso = yield addCoffee("", "에스프레소");
console.log(espresso);
// 앞 순서가 끝날때까지 기다렸다가 수행
var americano = yield addCoffee(espresso, "아메리카노");
console.log(americano);
var mocha = yield addCoffee(americano, "카페모카");
console.log(mocha);
var latte = yield addCoffee(mocha, "카페라떼");
console.log(latte);
};
var coffeeMaker = coffeeGenerator(); // 이터레이터 객체 반환
coffeeMaker.next(); // 실행 → coffeeGenerator 내부로 진입
async(비동기), await(기다리다)는 ES2017에 새롭게 추가됐습니다.
비동기 작업을 수행할 함수 앞에 async를 붙여주고 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await를 붙여주면 됩니다.
Promise ~ then과 동일한 효과를 얻을 수 있습니다.
// coffeeMaker함수에서 호출 할 함수. Promise를 반환 함
var addCoffee = function (name) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(name);
}, 500);
});
};
//
var coffeeMaker = async function () {
// 화살표 함수일땐
// var coffeeMaker = async () => {
var coffeeList = "";
var _addCoffee = async function (name) {
coffeeList += (coffeeList ? ", " : "") + (await addCoffee(name));
};
// promise를 반환하는 함수인 경우, await를 만나면 무조건 끝날 때까지 기다림
await _addCoffee("에스프레소");
console.log(coffeeList);
await _addCoffee("아메리카노");
console.log(coffeeList);
await _addCoffee("카페모카");
console.log(coffeeList);
await _addCoffee("카페라떼");
console.log(coffeeList);
};
// 호출
coffeeMaker();