지금까지 JS의 이터러블 객체를 중심으로 여러 함수들을 생성하였다.
예를 들어, map
, filter
, reduce
를 뼈대로 응용해서 함수합성등을 통해 L.map
,takeAll
, flatMap
등 응용 함수들을 만들었다.
하지만, L.map
, map
, take
는 기본적으로 동기적으로 돌아가는 상황에서만 정상적인 동작을 보장한다.
따라서, reduce
, pipe
처럼 비동기상황에서도 동작할 수 있는 함수로 만들어보자.
💡 이터러블 함수들에 대하여...
👉 JavaScript - 지연성(1)
👉 JavaScript - 지연성(2)
✅ Promise를 인자값으로 사용한 L.map
👎 비동기 처리를 하기 위한 Promise.resolve 를 사용할 경우, 정상적으로 동작하지 않는다.
go([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)],
L.map(a=>a+10),
take(2),
log
);
// 결과
//"[object Promise]10", "[object Promise]10"]
프로미스는 자바스크립트 비동기 처리에 사용되는 객체.
자바스크립트의 비동기 처리란 ‘특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성’을 의미.(참고)
✅ L.map에서 Promise를 받도록 적용
👍 Promise로 값을 받을 수 있는 go1함수에 이터러블한 값을 넘겨 프로미스의 체인으로 연결하여 예정된 값으로 만들어준다.
const go1 = (a, f) => a instanceof Promise ? a.then(f) : f(a);
L.map = curry(function* (f, iter) {
for (const a of iter) {
yield go1(a,f);
}
});
...
go([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)],
L.map(a=>a+10),
take(2),
log
);
//실행결과
//0: Promise {<fulfilled>: 11}
//1: Promise {<fulfilled>: 12}
✅ take에서 Promise내부의 값 꺼내어 반환
기존 take 함수에서 currentValue(cur.value)
이 Promise
일 경우 내부의 값을 then
을 통해 res Array
에 넣어준 뒤 재귀적으로 다시 유명함수 recur()
를 호출해 문제를 해결하고 있습니다.
const take = curry((l, iter) => {
let res = [];
iter = iter[Symbol.iterator]();
return function recur() {
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
if (a instanceof Promise)
return a.then(a => (res.push(a), res).length === l ? res : recur())
res.push(a);
if (res.length === l) return res;
}
return res;
}();
});
go([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)],
L.map(a=>a+10),
take(2),
log
); //[11,12]