RxJS does not completely refer to North (Beginner-Level Chapter)

  javascript, rxjs

What is RxJS?

RxJS is a JavaScript library for writingAsynchronousAndEvent-basedThe program. RxJS combinesobserver modeiterator patternAndFunctional Programming Using SetsIn order to satisfy the management in an ideal wayEvent sequenceEverything you need.

RxJS can be used to handle eventsLodash.

Why do you want to learn Rxjs?

In current Web development,Asynchronous (Async)Operations can be seen everywhere. For example, using ajax to submit a form data, we need to wait for the server to return the submission results and then perform subsequent operations. This is a typical asynchronous operation. Although JavaScript has proposed many solutions (callback, Promise, Async/await, etc.) to facilitate developers to operate asynchronously, as the requirements become more complex, howElegant management of asynchronous operationsIt is still a difficult problem.

In addition, asynchronous operation API is very strange and varied:

  1. DOM Events
  2. XMLHttpRequest
  3. fetch
  4. WebSockets
  5. Service Worker
  6. Timer
  7. ……

All of the above commonly used API are asynchronous, but each one is completely different to use, virtually increasing the cost of learning and memory for developers.

Using RxJS can help us solve the above two problems very well.Control the complexity of a large number of asynchronous codes, keep the code readable, and unify API.

For example, chestnut: there is a search box on the page. users can enter text to search. asynchronous requests should be sent to the server during searching. in order to reduce the pressure on the server, the front end needs to control the frequency of requests. requests should be sent up to 5 times per second, and no requests should be sent when the input is empty. finally, the search results should be displayed on the page.

In general, our method is as follows: firstly, whether the input is empty or not is judged; if not, an interception function is constructed to control the request frequency, which involves the creation and destruction of timers; in addition, since the return time of each request is uncertain, how to obtain the last search result requires the construction of a stack to save the request sequence, and it is not simple to realize the requirements perfectly.

How does RxJS solve this problem? Please look at the following code:

// 1. Get dom Elements
 const typingInput = document.querySelector("#typing-input");  //Input
 const typingBack = document.querySelector("#typing-back");  //output
 
 // 2. Simulate asynchronous requests
 const getData = value =>
 new Promise(resolve =>
 setTimeout(() => resolve(`async data ${value}`), 1000)
 );
 
 // 3.RxJS operation
 Constsource $ = fromevent (typeinput, "input")//creates an event data stream
 . pipe( // pipe type operation
 Map(e => e.target.value), // get input data
 Filter(i => i), // filter empty data
 DebounceTime(200), // control frequency
 SwitchMap(getData) // convert data to request
 );
 // 4. Enter the results
 source$.subscribe(asyncData => (typingBack.innerHTML = asyncData));

This is all the code, maybe some places don’t understand, it doesn’t matter, don’t worry, let’s read it step by step.

  1. The selector was used to obtain two dom elements, the first is the input box and the second is the container of search results.
  2. Use Promise to simulate an asynchronous request function and return the request result after 1 second;
  3. This part is RxJS operation. Here we will first introduce a concept.“stream” (Stream for short)“Flow” is a special object in RxJS. We can imagine that data flow is like a river, and data is the water in the river, flowing down the river.Variables representing “flow” usually end with “$”, which is a convention in RxJS programming and is called “Finnish nomenclature”.
    The source$ in the code is generated by the input event in the input boxdata flow, we can use the pipe method to process the data in the stream like building a “pipeline”. First, we use the map function to convert the event object into an input value, then use the fllter method to filter out invalid inputs, then use debounceTime to control the frequency of data downward flow, and finally use switchMap to convert the input value into an asynchronous request, thus completing the construction of the entire data stream.
  4. Finally, we use the subscribe method of data stream to add operations on the data, that is, to output the requested results to the page.

    Note that all the variables we use in this code are declared with const and are all immutable, that is, whatever value a variable is declared is always what value, just like defining a function. Compared with traditional instruction-based programming, RxJS code is composed of one immutable function after another. Each function only makes corresponding input parameters and then returns the result. Such code is writtenMore refreshing and better maintenance.

RxJS combinesFunctional expressionAndResponsiveFor a deeper understanding of RxJS, let’s first introduce what functional programming and reactive programming are.

Functional programming

Functional Porgramming is a kind ofProgramming paradigm, like “object-oriented programming”, is a kind of writing code“Methodology”, tell us how to think and solve the problem. Unlike object-oriented programming, functional programming emphasizes the use of functions to solve problems.

Here are two questions:

  1. Does any language support functional programming?No, languages that can support functional programming must at least satisfy “The function is a First Class“This requirement means that a function can be assigned to a variable and can be passed as a parameter to another function or as the return value of another function. Obviously JavaScript meets this condition.
  2. What is special about functions in functional programming?Functional programming requires functions to meet the following requirements:Declarative, pure function, data immutable.

Declarative

Corresponding to this is imperative programming, which is also the most common programming mode.

For example, we want to write a function, multiply each element in the array by 2, and use imperative programming, which looks like this:

function double(arr) {
const result = []
for(let i=0,l=arr.length;  i<l;  i++) {
result.push(arr[i] * 2)
}
return result
}

We have described the whole logic process completely and perfectly.

But if there is a new requirement, implement a new function, add 1 to each element in the array, simple, and do it again:

function addOne(arr) {
 const result = []
 for(let i=0,l=arr.length;  i<l;  i++) {
 result.push(arr[i] + 1)
 }
 return result
 }

Does it feel wrong? Double and addOne have 90 percent of the same code. “Repeated codes are the root of all evil.“We should think of some way to improve it.

This shows a problem of imperative programming. The program is executed according to logical process, but many problems have similar patterns, such as double and addOne above. Naturally, we want to abstract this pattern to reduce duplication of code.

Next we use JavaScript’s map function to rewrite double and addOne:

function double(arr) {
 return arr.map(function(item) { return item * 2 })
 }
 
 function addOne(arr) {
 return arr.map(function(item) { return item + 1 })
 }

The duplicate code is all encapsulated into the map function. All we need to do is tell the map function how to map the data, and that isdeclarative programming. Compared with previous codes, such codes are easier to maintain.

If the arrow function is used, the code can be further simplified:

const double = arr => arr.map(item => item * 2)
 
 const addOne = arr => arr.map(item => item + 1)

Note that the return results of the above two functions are a new array, and the original array has not been modified, which meets another requirement of functional programming:Pure function.

Pure Function

Pure function refers to a function that satisfies the following two conditions:

  1. Input the same parameters and return the same output results;
  2. No external state, such as global variables or passed-in parameter objects, will be modified within the function.

Take a chestnut:

const arr = [1, 2, 3, 4, 5]

arr.slice(0, 3) // [1, 2, 3]

arr.slice(0, 3) // [1, 2, 3]

arr.slice(0, 3) // [1, 2, 3]

The slice method of an array in JavaScript returns the same value no matter how many times it is executed and does not change any external state, so slice is a pure function.

const arr = [1, 2, 3, 4, 5]

arr.splice(0, 3) // [1, 2, 3]

arr.splice(0, 3) // [4, 5]

arr.slice(0, 3) // []

On the contrary, the result of each call to the splice method is different, because the splice method changes the value of the global variable arr, so splice is not a pure function.

Unpure functions often produce someSide Effect, such as the following:

  1. Changing global variables;
  2. Changing the input parameter reference object;
  3. Read user input, such as calling alert or confirm function;
  4. Throws an exception;
  5. Network I/O, such as sending an AJAX request;
  6. Operate DOM;;

Using pure functions can greatly enhance the maintainability of the code, because fixed inputs always return fixed outputs, so it is easier to write unit tests and less prone to bugs.

Data Immutability

Data immutability is a very important concept in functional programming, which means that if we want to change the value of a variable, instead of directly modifying the variable, we can call a function to generate a new variable.

If you are a front-end engineer, you must have already realized the benefits of unchangeable data. In JavaScript, the two types of String and Number are immutable, and it is not easy to make mistakes when using them, while the type of Array is changeable. pop, push and other methods of array will change the original array object, thus causing various bugs.

Note that although ES6 has proposed using const to declare a constant (immutable data), this can only ensure that the reference of the declared object cannot be changed, while the object itself can still be changed. For example, if you declare an array with const, you can still add elements to the array with push method.

Compared with object-oriented programming, object-oriented programming tends to encapsulate the changes of state inside the object, thus making the code clearer. However, functional programming tends to separate data from functions. Functions can process data but do not change the original data. Instead, new data is generated as the operation result to minimize the changed parts and make our code clearer.

Responsive programming

Similar to functional programming, Reactive Programming is also a programming paradigm. From the point of view of design pattern, responsive programming is an effective practice of “observer pattern”. In short,Responsive programming refers to actively notifying the data user of the change when the data changes..

Many students have used vue framework for development. The well-known data bidirectional binding in vue is realized based on the design idea of responsive programming. When we bind a data to a component through v-bind, no matter when the data changes, we will actively notify the bound component, so that we can focus on processing the data itself during development without paying attention to how to synchronize the data.

The most famous framework in programming at the corresponding time was developed by MicrosoftReactive Extension. This framework is designed to help developers solve complex asynchronous processing problems. Our protagonist RxJS is the JS version of this framework.

How to use RxJS

Installation

npm install rxjs

Import

import Rx from "rxjs";

Please note that such import will import the entire RxJS library, but the actual project may not use all the functions of Rxjs. All import will make the project become very large after packaging. We recommend using deep link to import Rxjs, and import only the functions used. For example, if we want to use the Observable class, we will import it only:

import { Observable } from "rxjs/Observable";

In actual projects, on-demand import is a good method, but if each file is written with a bunch of import statements, it would be too much trouble. Therefore, a better practice is toUse one file to import RxJS related functions, and import other files into this file to import RxJS for centralized management..

Space is limited, the next lecture will explain some core concepts in RxJS, welcome to leave a message and clap bricks ~