Good code usually has one characteristic: high cohesion and low coupling.

In plain English, this means to accomplish more functions with less code. For example, the Web front-end MVVM framework abstracts operations and event listeners on the DOM and updates data and views through data binding.

The same goes for the idea of componentization, where the purpose of a component is not simply to split code, but to reuse it.

These are optimizations at the view level, but there are ways to write better code at the data level.

One simple and effective way to do this is to write pure functions as often as possible.

Pure functions

What is a pure function? You can use an expression to describe it

Input parameter x => execute code => output y

This may seem like a normal function, but how pure is it compared to a normal function?

  • From the input, parameters are mandatory and cannot be modified. A function with no arguments, such as Math.random, is not pure.

  • From an execution point of view, external variables or functions cannot be referred to.

  • From the result point of view, execution must have results, and the same input parameters, execution must be the same result.

A pure function is the ultimate separation of logic: a piece of single-function, logically closed code.

Function (x) {return 1} function(x) {return 1}

If you use pure functions in your code, there are the following benefits:

  • Easy to test. As any front-end developer who has written unit tests knows, front-end unit tests are difficult to write, and one of the big reasons is that there are too many “impure” functions. A function might manipulate the DOM, send Ajax requests, or reference unknown global variables… AngularJS directly points out in its official documentation that some highly coupled code is difficult to test, so this is why MVVM frameworks have become popular in recent years. Frameworks take over the DOM manipulation and developers write the logic to make the code logic clearer.

  • Reusable. Those of you writing server-side node.js will be familiar with the term “isomorphism”, meaning that a piece of JS code can run on both server-side and browser-side, while pure functions support isomorphism.

  • No side effects. Multiple impure functions modifying a variable (or manipulating a DOM element) at the same time, coupled with asynchrony, can easily cause conflicts. Pure functions don’t modify input arguments or external variables, so don’t worry about it at all.

RxJS

Third-party open source libraries that match the nature of pure functions include the well-known underscore and LoDash, as well as the more powerful RxJS.

RxJS is Microsoft launched ReactiveX series (RxJava, Rx.NET, RxScala, RxSwift, etc.), one of the star number on the lot at present has more than 17 k.

It can be used to gracefully handle asynchrony and events. It is mainly implemented through its core type Observable and powerful operators (map, filter, reduce, every, etc., most of which are pure functions).

The most straightforward official definition of it is

Think of RxJS as Lodash for handling events.

Take a look at the official code:

Var count = 0; var count = 0; var rate = 1000; var lastClick = Date.now() - rate; var button = document.querySelector('button'); button.addEventListener('click', () => { if (Date.now() - lastClick >= rate) { console.log(`Clicked ${++count} times`); lastClick = Date.now(); }}); Var button = document.querySelector('button'); Rx.Observable.fromEvent(button, 'click') .throttleTime(1000) .scan(count => count + 1, 0) .subscribe(count => console.log(`Clicked ${count} times`));Copy the code

RxJS code eliminates some intermediate variables and uses operators to step through the logic, making it more readable, less coupled, and easier to test and modify.

RxJS will be covered in more detail in future articles, but this article will first talk about its applications. There are many articles about the application of RxJS on the Web side and node.js server side, so this time we break the convention and talk about the use of small programs in the development of wechat (hereinafter referred to as “small programs”).

Small program

Is directly used in the small program RxJS complains, so I set up an open source project to solve the problem: RxWX (project address: https://github.com/yalishizhude/RxJS).

Encapsulates two JS files.

  • Rx. Js. Some modifications have been made to rx.js to make it run in applets.

  • RxWX. Js. Based on rx.js, the API of wechat is encapsulated. Calling the API of the same name no longer uses callback, but returns an Observalbe object.

The installation

Two installation methods are provided

Github

git clone https://github.com/yalishizhude/RxWX.git

You can download the project directly and copy the rx.js and rxwx.js files from the root directory into the applets project, or you can visit the web site to copy and paste the contents of the two files.

npm

npm i rxjs-wx

Copy rx. js and rxwx. js from node_modules/rxjs-wx to your applet project.

use

Most applets’ apis are not designed with a pure function in mind, assigning the return result to the success, fail, and complete attributes of the input parameter.

It’s easy to fall into callback hell when the logic is simple and complex, and the way synchronous and asynchronous interfaces are invoked is inconsistent. These problems can be solved using RxJS. Here are some examples.

To deal with the callback

Suppose you have a requirement to get user information through wx.getUserInfo and then pass it to the back-end service to get additional information about the user to display on the page.

// let self = this wx.getUserInfo({success: (res) => {wx.request({method: 'GET', url: 'XXX /user', data: res.userInfo, success(r) { self.setData({userInfo:r}) }, fail(e) { self.setData({userInfo:'not found'}) } }) }, Fail (e) {console.error(e)}}) // Use RxWX import obs from './RxWX' obs.getUserInfo().catch(e => console.error(e)) .switchMap(({ userInfo }) => obs.request({ method: 'GET', url: 'xxx/user', data: user })) .subscribe(userInfo => self.setData({ userInfo: r }), e => self.setData({ userInfo: 'not found' }))Copy the code

Handle events

I once encountered a serious problem when using navigator component in the development of small programs: multiple page jumps would occur when clicking quickly and repeatedly. After the jump, I needed to click “Return” for several times to return to the original page.

To solve this problem, you can usually manually bind events and then perform an anti-shake operation.

// Common code let tapping = false... tap(e) { if(! tapping) { wx.navigateTo({ url: '.. /demo/demo' }) tapping = true setTimeout(() => tapping=false, NavigateTo ({url: '.. ') {navigateTo({url: '.. ') {navigateTo({url: '.. /demo/demo' }) .debounce(1000) .subscribe() }Copy the code

other

RxWX also supports other non-functional properties of WX objects, such as:

Import obs from './RxWX' console.log(obs.version) // {info:"", updateTime:"2017.7.10 19:35:05", version:"1.4.0"}Copy the code

The last

RxJS and RxWX are third-party libraries that are a gateway into the world of pure functions and a way of thinking about writing better code.

This article may be forwarded or shared, but must retain the complete picture and text information and source, the author reserves the right to investigate all legal responsibility and means ~

Search the concerned public number “Web learning club” ~