[async/await]

function delay(time) {
  return new Promise(resolve => setTimeout(() => resolve(), time));
}

async function delayIdentity(a) {
  await delay(500);
  return a; // Promise 리턴
}

async function f1() {
  const a = await delayIdentity(10);
  const b = await delayIdentity(5);
  return a + b; // Promise 리턴
}

f1(); // Promise
f1().then(log); // 15
go(f1(), log); // 15

const pa = Promise.resolve(10);

(async () => {
	 log(await pa); // 10 // 이렇게 꺼내볼수 있다
})();

[Q&A]

[Array.prototype.map이 있는데 왜 FxJS의 map 함수가 필요한지?]

function delayI(a) {
  return new Promise(resolve => setTimeout(() => resolve(a), 100));
}

// Array.prototype.map 로 Promise 제어 해보기
async function f2() {
  const list = [1, 2, 3, 4];
  const temp = list.map(async a => await delayI(a * a));
  log(temp);// Prmoise의 배열

	// 아무리 async 함수를 쓴다고해도 map이 Promise를 제어해주지 않기 때문에
	// 해당 문제가 해결이 되지 않는다

	const res = await temp;
	// temp는 그냥 배열이라서 이위에 await를 달아서 풀려고 해도 풀 수 없는것
	log(res);
}

f2();

// FxJS map 로 Promise 제어 해보기
async function f3() {
  const list = [1, 2, 3, 4];
  const temp = map(a => delayI(a * a), list);
  log(temp);// Promise pending // 미리 배열을 다만들어서 배열자체가 pending 되어 있게 되어있음

  const res = await temp; 
  log(res); // [1 4 9 16]
}

f3();

function f4() {
  return map(a => delayI(a * a), [1, 2, 3, 4]);
}

(async () => {
  log(await f4()); // Promise를 전달받아서 async await를 품
})();

[이제 비동기는 async/await로 제어할 수 있는데 왜 파이프라인이 필요한지?]

둘은 전혀 다른 상황의 해결책, 그것을 해결하기 위한 기술 이다

function f5(list) {
  return go(list,
    L.map(a => delayI(a * a)),
    L.filter(a => delayI(a % 2)),
    L.map(a => delayI(a + 1)),
    C.take(2),
    reduce((a, b) => delayI(a + b)));
}

go(f5([1, 2, 3, 4, 5, 6, 7, 8]), a => log(a, 'f5'));

// f5의 파이프라인은 단순히 명령형적인 부분을 함수형을 고치는데 제일 큰 목적이 있다
// 테스트도 쉽고 유지보수도 쉽다
// take 대신 C.take를 써서 최대한 빠르게 실행도 가능하다

// f5를 async await로 명령형으로 풀어써 본 f6
async function f6(list) {
  let temp = []
  for (const a of list) {
    const b = await delayI(a * a);
    if (await delayI(b % 2)) {
      const c = await delayI(b + 1);
      temp.push(c);
      if (temp.length == 2) break;
    }
  }
  let res = temp[0], i = 0;
  while (++i < temp.length) {
    res = await delayI(res + temp[i]);
  }
  return res;
}

// 동기 비동기가 없는상황이 되면 엄청난 변화가 또 필요하다
// 재활용이 불가능한 코드
// 이 코드가 위 코드로 변하는것도 상당히 어렵다
// 아래 코드가 위 코드처럼 동시성 으로 최대한 빠르게 처리하려고하면 엄청난 변화가 또 필요하다

go(f6([1, 2, 3, 4, 5, 6, 7, 8]), log);

// async await와 파이프라인은 쓰는 목적이 다르다

[async/await와 파이프라인을 같이 사용하기도 하나요?]

async function f52(list) {
  const r1 = await go(list,
    L.map(a => delayI(a * a)),
    L.filter(a => delayI(a % 2)),
    L.map(a => delayI(a + 1)),
    C.take(2),
    reduce((a, b) => delayI(a + b)));

  const r2 = await go(list,
    L.map(a => delayI(a * a)),
    L.filter(a => delayI(a % 2)),
    reduce((a, b) => delayI(a + b)));

  const r3 = await delayI(r1 + r2);

  return r3 + 10;
}

go(f52([1, 2, 3, 4, 5, 6, 7, 8]), a => log(a, 'f52'));