관리 메뉴

흰둥씨의 개발장

[#8] 비동기 이벤트와 데이터 관리 본문

함수형 프로그래밍/함수형 자바스크립트

[#8] 비동기 이벤트와 데이터 관리

돈워리비해삐 2023. 9. 17. 01:23

비동기 코드 개발의 어려움 

비동기 요청은 
  1. 함수간 일시적 의존 관계가 형성됨 (데이터 도착할때까지 or 다른 함수가 실행될 때까지 어떤 함수가 기다리는 경우)
  2. 콜백의 늪에 빠짐 (이벤트가 발생하면? 콜백함수를 실행하는데 그와중에 에러나면 또 에러 콜백 호출되고... 복잡도 증가)

 

함수형기법과 프로미스를 사용해서 비동기 코드를 능률적으로 ! 

=> 위 문제를 해결하기 위해서
  1. 연속체 전달 스타일 continuation-passing style 사용 (콜백함수를 모두 개별 함수로 나눠서 개별컴포넌트처럼 취급)
  2. 비동기 로직을 Promise로 일급화 하기 
      프로미스의 상태는 항상 pending(unresolved), fulfilled, rejected, settled 중 하나로
      fulfilled는 resolve함수를 호출 / rejected는 reject함수를 호출
      프로미스 생성자는 액션함수 하나를 받음 (이 액션함수는 resolve, reject콜백 2개를 받고, 각각 프로미스 상태에 따라 호출)

let fetchData = new Promise((resolve, reject) => {
	//성공하면 ? 
	return resolve(res);
    //실패하면 ?
    reject(new Error('에러발생');
}

      프로미스는 모나드 map처럼 아직 존재 하지 않는 미래의 값을 변환하는 객체
      비동기 호출을 중첩하는 대신 then으로 체이닝 하고, 비동기 코드를 프라미스 모나드로 추상화 하기
      에러 처리 로직을 catch에 몰아두기
      여러 데이터를 내려받을때는 이터러블을 응용한 Promise.all사용하기
    => 프로미스를 쓰면 동기 프로그래밍의 모양을 유지한 상태에서 시차를 두고 여러 함수 나누어 실행가능

 

함수 제너레이터로 데이터를 느긋하게 

제너레이터 ? 함수에 애스터리스크(*)를 붙인 함수로 yield를 만나면 함수 밖으로 잠시 나갔다가 자신의 context를 찾아 돌아옴

function* 프론트(){
	yield "후론트라라! 후론트라라! 후론트루루 라라라";
}
프론트();// 프론트 {<suspended>}
프론트().next().value; //"후론트라라! 후론트라라! 후론트루루 라라라"
function* range(start = 0, finish = 100){
	for(let i = start; i < finish ; i++){
    	yield i;
    }
}

const 숫자생성기 = range(1);
숫자생성기.next().value; //1
숫자생성기.next().value; //2
숫자생성기.next().value; //3
숫자생성기.next().value; //4

const num = range(50);
num.next().value;//50
num.next().value;//51

제너레이터 함수는 호출 시점에 내부적으로 이터레이터 객체 생성해서 느긋함을 부여하고, 
이터레이터는 yield를 호출할 때마다 호출자에게 데이터를 돌려줌 

//제너레이터로 구현한 range를 원시로 구현
function range(start, end){
	return {
    	[Symbol.iterator](){
        	return this;
            },
         next(){
         	if(start < end){
            	return {value: start++, done:false };
               }
            return { done: true, value: end };
            }
         }
}
const num = range(1,10);
num.next().value; //1
num.next().value; //2
num.next().value; //3

 

 

리액티브 프로그래밍  =  Rx.js

1. 옵저버블 순차열로서의 데이터

Rx.Observavle ? 구독 가능한 모든 객체 

Rx.Observable.range(1,3).subscribe(
			    x => console.log(`순차열의 각원소를 처리하는 함수: 다음 ${x}`),
                            err => console.log(`에러시 실행되는 함수: ${err}`),
                            () => console.log(`끝나면 실행되는 함수`)
                         );
                         
//함수 실행시 아래와 같이 동작 
순차열의 각원소를 처리하는 함수: 다음 1
순차열의 각원소를 처리하는 함수: 다음 2
순차열의 각원소를 처리하는 함수: 다음 3
끝나면 실행되는 함수
//함수형도구들도 Observable로 묶을수 있음 
Rx.Observable.of(1,2,3,4,5)
	.filter(x => x % 2 !== 0)
    .map(x => x * x);
    .subscribe(x => console.log(`출력: ${x}`));
    
//실행시 
출력: 1
출력: 9
출력: 25

 

2. Rx.js 는 프라미스를 옵저버블 순차열로 변환할수 있음