리버스 엔지니어링 RXJ를 어떻게 리액션 프로그래밍을 배웠습니까?

네, 제목은 타자 오류가 아닙니다.실제로 RxJs에 대해 리버스 엔지니어링을 진행합니다(이후에는 대량의 코드가 있을 것입니다).하지만 우리가 계속하기 전에, 내가 왜 이 미친 노력을 시작해야 하는지 알려줄게.
프로그래머로서 우리는 천성적으로 호기심이 많다.나는 RxJs와 React 등 반응성 라이브러리를 사용한다.맨날.그러나 햇살이 쨍쨍한 아침에 나는 이 구조들이 어떻게 막후에서 반응식 프로그래밍을 활용하는지 궁금했다.

Do I really understand what reactive programing is? How does it actually work? I asked myself.


주말 동안 블로그 게시물과 서적에 대한 발굴을 통해 나는 이 개념을 조금 알게 되었다.그러나 나는 역방향 공사가 개념을 진정으로 확정하는 좋은 방법이라고 생각하기 때문에 역방향 공사 RxJs를 결정했다.

간략한 설명:


반응식 프로그래밍은 비동기 데이터 흐름 프로그래밍을 사용한다.

The Data streams could be anything, it could be user inputs (i.e. position of your mouse, click events), it could be streams of data from a server (i.e. your twitter feed, or real time data from a socket server). Our Application will react according to these streams of data.


예를 들어 프로그램에서 트위터 구독원을 실시간으로 수신할 때 상태가 달라진다.아마도 너는 가장 환영받는 트윗을 위에 놓고 싶을 것이다.따라서 응용 프로그램은 전송된 데이터 흐름을 구독하고 데이터에 반응하며 가장 유행하는 트윗을 맨 위에 놓습니다.간단히 말하면 구독 데이터 흐름과 응용 프로그램의 개념을 바꾸는 것은 반응식 프로그래밍이다.
심심해요?나를 믿어라, 이것은 많은 개념이 있는 블로그 문장이 아닐 것이다.우리는 지금 코드를 깊이 연구할 것이다.
RxJs의 가장 기본적인 구축 블록이기 때문에 Observable라는 클래스를 구축합시다.
class Observable {
  constructor() {
    this.fnArray = [];
  }

  subscribe() {}

  emit() {}
}

const o = new Observable();
알겠습니다. Observable라는 기본 클래스를 만들었습니다. 두 가지 방법이 있습니다.fnArray라는 빈 목록을 초기화했습니다.이 그룹은 모든 구독 대상을 저장합니다.
먼저 subscribe 방법을 실현합시다.이 방법은 함수를 매개 변수로 삼아 우리의 수조로 전송합니다.
subscribe(fn) {
    this.fnArray.push(fn);
}
이제 우리도 emit 함수를 실현하자.emit 함수의 임무는 순환 fnArray 이며, 이 함수들을 하나씩 실행합니다.
emit(v) {
  for (let fun of this.fnArray) {
    fun(v);
  }
}
우리도 for 순환을 지도로 대체할 수 있다.근데 왜죠?이게 JS지역의 쿨한 아이들이 지금 하고 있는 일이야.카레 기능도 멋져!!그럼 우리 지금부터 시작합시다.
emit(v) {
-  for (let fun of this.fnArray) {
-    fun(v);
-  }
+  this.fnArray.map(fun => fun(v))
}
자, 이제 새로 만든 클래스를 사용하겠습니다.
function printFunction(thing) {
 console.log(`I will print the ${thing}`)
}

const o = new Observable();
o.subscribe(printFunction);
우선, 전송된 변수를 인쇄하는 데 사용할 함수 printFunction 를 만들었습니다.우리는 새로운 관찰 가능한 실례를 초기화하여 subscribe 방법을 호출하고 printFunction를 매개 변수로 전송했다.
기억하십시오printFunctionfnArray에 저장됩니다.지금 만약 우리가 emit 방법을 호출한다면, 당신은 무슨 일이 발생할 것이라고 생각합니까?한번 해봅시다.
o.emit("Apple");
o.emit("Orange");
o.emit("Pear");
이것은 우리에게 다음과 같은 출력을 제공했다
I will print the Apple
I will print the Orange
I will print the Pear
자, 이제 함수나 이벤트를 구독하고 그 함수를 바탕으로 뭔가를 보낼 수 있습니다.지금까지 코드 전체가 이랬다.
class Observable {
  constructor() {
    this.fnArray = [];
  }

  subscribe(fn) {
    this.fnArray.push(fn);
  }

  emit(v) {
    this.fnArray.map(fun => fun(v));
  }
}

function printFunction(thing) {
  console.log(`I will print the ${thing}`);
}

const o = new Observable();
o.subscribe(printFunction);

o.emit("Apple");
o.emit("Orange");
o.emit("Pear");
이제 재미있는 부분으로 들어갑시다.우리는 다양한 기능을 구독할 수 있다.예컨대 우리는 이런 일을 할 수 있다
o.subscribe(x => console.log(x * 2));
o.subscribe(x => console.log(x + 2));

o.emit(4)
얘가 돌아왔어요.
// 8
// 6
클래스 구조 함수에서 초기화된 함수 그룹의 모든 함수를 반복하기 때문입니다.

notice that I am using arrow function now. We are also able to compose our functions with any combinations we wish.


const square = num => num * num;
o.subscribe(x => printFunction(x * 2));
o.subscribe(x => printFunction(square(x)));
o.emit(4);

// outputs

// I will print the 8
// I will print the 16
첫 번째 장면에서 우리는 printFunction 조합 함수를 사용한다.두 번째 장면에서 우리는 square 함수를 만들고 printFunction로 그것을 조합했다.
이거 좀 멋있지 않아요?
좋아, 우리는 함수를 조합할 수 있지만, 우리는 그것들을 조합하는 더 좋은 방법이 필요하다.더 전면적인 것, 예를 들어 RxJS의pipe.그래서 이 메커니즘을 세우자.
const pipe = (f, g) => x => g(f(x));
pipe라는 새 함수를 정의했습니다. 이 함수는 2개의 함수를 매개 변수로 하고, 이 함수는 매개 변수를 받아들인 다음 조합 함수 f of g를 되돌려줍니다.
방금 무슨 일이 있었어요?
우리는 두 함수를 매개 변수로 한다.그리고 우리는 다른 값을 매개 변수로 삼아 첫 번째 함수f와 값x을 적용한다.그리고 우리는 반환값f(x)과 응용 함수g를 찾았다.
이것은 좀 곤혹스러울 수 있습니다. 만약 당신이 그렇다면, 자바스크립트로 읽어 보시기를 강력히 권장합니다. currying function지금 파이프 기능을 사용하면 우리는 이런 일을 할 수 있다
o.subscribe(
 pipe(
   square,
   printFunction,
 )
)
o.emit(4);

// outputs
// I will print the 16
근데 여기 문제가 있어요.우리는 임의의 수량의 함수를 전달할 수 있기를 희망한다. 그리고 우리는 그것들을 조합할 수 있어야 한다.하면, 만약, 만약...⇒ k(h(g(f))).
그래서 저희가 이렇게 파이프를 고쳐야 돼요.
const pipe = (...funcs) => x => funcs.reduce((effects, f) => f(effects), x);
이게 무슨 마법이야?우선, 우리는 확장산자로 일부 함수를 도입했다.(...funcs) 부분에서 우리는 임의의 수량의 함수를 순서대로 받아들일 수 있다고 규정했다.그리고 우리는 하나의 값x을 매개 변수로 연산할 것이다.funcs.reduce는 모든 함수를 검사하고 x의 업데이트 값을 되돌려 시리즈의 다음 함수에 전달합니다.이것을 일련의 집행으로 간주하다.실행이 끝났을 때x는 여전히 같다. 왜냐하면 우리는 변경되지 않았기 때문이다pure functions.의 값

More on pure function in my next article so stay tuned 😊


이제 우리가 왜 이러는지 알려줄게.다음 코드를 보도록 하겠습니다.
o.subscribe(
 pipe(
   square,
   double,
   square,
   printFunction
 )
);
o.emit(2);

// outputs
// I will print the 64
봐라, 지금 우리는 함수를 조합할 수 있으니, 그것들의 순서에 너무 신경 쓰지 마라. 우리는 데이터가 변하지 않을 수도 있다.
그러나 우리의 실현에는 한 가지가 부족하다.우리는 파이프 사이에서 데이터를 수집할 수 없다.내 말은 두 번째double를 응용한 후에 우리는 우리의 가치를 파괴하고 수집할 수 없다는 것이다.RxJs에는 이를 실현할 수 있는 tap 방법이 있다.tap 방법을 실현합시다.
const tap = fun => x => {
 fun(x);
 return x;
};
이 방법에 대해 우리는 함수와 값을 얻은 다음에 값과
원래 값을 반환합니다.이런 방식을 통해 현재 우리는 파이프의 특정 위치의 값을 클릭하고 꺼낼 수 있다.
o.subscribe(
 pipe(
   square,
   double,
   tap(printFunction),
   square,
   printFunction
 )
);
o.emit(2);

// outputs
// I will print the 8
// I will print the 64
거의 이렇다.기술적으로 RxJS 등 반응식 라이브러리의 기본 기능을 갖추고 있습니다.***지금 저는 여러분께 우리의 반응식 라이브러리 ***의 실제 실현을 보여드리고 싶습니다.
만약 우리가 전송한 비동기적인 데이터가 있다면예를 들어 마우스 포인터의 위치는 하나의 예가 될 수 있다. 이러한 데이터를 바탕으로 내 프로그램에서 상태 변경을 실행하고 싶다.이것이 바로 우리가 어떻게 우리의 반응식 라이브러리를 사용하여 이 문제를 처리할 것인가 하는 것이다
o.subscribe(pipe(
 filter(x => {
   if(x > 0) {
     console.log('In Range')
     return x;
   }
   console.log('Out of Range')
   return 0
 }),
 square,
 tap(printFunction),
));

o.emit(2);
o.emit(-4);
o.emit(8);
o.emit(4);
// outputs
// In Range
// I will print the 4
// Out of Range
// I will print the 0
// In Range
// I will print the 64
// In Range
// I will print the 16
그래서 우리는 RxJS처럼 우리의 라이브러리를 사용하여 이 점을 실현할 수 있다funnel like data filtering.나는 이것이 너로 하여금 RxJS가 배후에서 어떻게 작동하는지 이해하게 할 수 있기를 바란다.

In Part 2 we will further break down all the operations of RxJS. Stay tuned, leave a comment if you have any feedback, follow me for more articles like this


⚡️⚡️⚡️⚡️⚡️⚡️
지금까지 재밌게 놀았어요?2부 봐주세요.🕟 🕔 🕠 🕕.

좋은 웹페이지 즐겨찾기