Search
🏛️

[FP & JS ES6+] 6. 비동기: 동시성 프로그래밍 (3) - async/await, Q&A

[FP & JS ES6+] 6. 비동기: 동시성 프로그래밍 (3) - async/await, Q&A
Javascript
Functional Programming
Study
2023/10/0614:19
[FP & JS ES6+] 6. 비동기: 동시성 프로그래밍 (3) - async/await, Q&A
Javascript
Functional Programming
Study
2023/10/0614:19

1. async/await

비동기 상황을 보다 동기적인 코드로 다루기 위한 또하나의 방법
promise를 다루면서 평가시점을 제어하고 싶을 때 사용
async를 선언하면 Promiose 객체를 리턴함
async 함수의 결과값을 외부에서 사용하고 싶을 경우, .then을 통해 처리
function delay(a) { return new Promise(resolve => setTimeout(() => resolve(a), 500)); } async function f1() { const a = await delay(10); const b = await delay(5); return a + b; } log(f1()); // Promise { <pending> } log(await f1()); // 15 f1().then(log); // 15
JavaScript
복사

2. Q&A

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

Array.prototype.map
내부적으로 보조함수에서 promise가 리턴되거나 보조함수를 async 함수로 선언한다고 해서, map이 promise를 제어해주진 않음.
안에서 비동기 상황을 제어할 수 없음
결과 값을 변수에 저장하여 출력을 해보면 단지 promise가 담긴 배열에 불과함
따라서, map 함수 자체가 promise 객체를 제어할 수 있어야함
FxJs.map
map 함수 자체가 promise 객체를 제어 가능
import {map} from '../0_common/fx.js'; async function delayI(a) { return new Promise(resolve => setTimeout(() => resolve(a), 100)); } // array.prototype.map async function f2() { const list = [1, 2, 3, 4]; const temp = list.map(async a => await delayI(a * a)); console.log(temp); // [Promise, Promise, Promise, Promise]. Promise 객체들의 배열 const res = await temp; console.log(res); } f2(); // 직접 구현한 map async function f3() { const list = [1, 2, 3, 4]; const temp = map(a => delayI(a * a), list); console.log(temp); // Promise 객체. 배열 [1, 4, 9, 16]이 resolve될 준비가 되어있음 const res = await temp; console.log(res); // [1, 4, 9, 16] } f3();
JavaScript
복사

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

파이프라인/iterable이 해결하려고 하는 문제와 async/await가 해결하려는 목적이 다르다.
async/await
비동기 프로그래밍을 작성할때, 표현식으로 갇혀있는 (Promise.then.then) 과 같이 함수 체인이 아니라 문장형으로 다루기 위한 목적
함수를 합성하는 게 아니라 반대로 풀어놓기 위한 목적
파이프라인/iterable
비동기 프로그래밍을 위해서가 아니라, 명령형 프로그래밍을 하지 않고 안전하게 함수 합성을 하는 것
함수를 합성하기 위한 목적
비동기/동기 상황이냐가 관심이 있는 것이 아님

2.3. async/await와 파이프라인을 같이 사용하기도 하는지?

파이프라인으로 연산된 결과를 async/await를 통해 동기적으로 조합하여 사용 가능

2.4. 동기 상황에서 에러 핸들링은 어떻게 해야하는지?

여러가지 방법으로 에러 핸들링 가능 (디폴트 값을 넣는 등.. 방어로직 추가)
function f8(list) { return (list || []) .map(a => a + 10) .filter(a => a % 2) .slice(0, 2); } log(f7(null));
JavaScript
복사
가장 적절한 방법은 try catch문을 활용하여 오류 제어

2.5. 비동기 상황에서 에러 핸들링은 어떻게 해야하는지?

promise를 잘 제어할 수없는 파이프라인 코드는 에러핸들링이 잘 안됨
catch 문에 도달하기전에 오류가 raise 됨
async/await & .then().catch 등을 사용해도 핸들링 되지 않음
비동기에서 에러 핸들링을 처리하기는 어렵다.
async function f8(list) { try { return await list .map(async a => await new Promise(resolve => { dlfjaf; })) .filter(a => a % 2) .slice(0, 2); } catch (e) { console.log(e); return []; } } f8(['0', '1', '2', '{']).then(a => console.log(a)).catch(e => console.log(e));
JavaScript
복사

2.6. 동기/비동기 에러핸들링에서의 파이프라인의 이점은?

try 안에서 비동기적으로 일어나는 함수가 catch에서 에러가 핸들링되기위해서는 try 내의 값이 promise.rejectd로 평가되어야함
지연 평가가 이루어지는 함수들 (L.map, L.filter) 들을 활용한다면 에러가 발생하지 않는 경우도 나올 수 있음
import {filter, go, map, take} from '../0_common/fx.js'; async function f9(list) { try { return await go(list, map(a => new Promise(resolve => { resolve(JSON.parse(a)); })), filter(a => a % 2), take(2)); } catch (e) { console.log(e, '-----------------------'); return []; } } f9(['0', '1', '2', '{']).then(a => console.log(a));
JavaScript
복사