Observer model

The observer model is also called the publish and subscribe model. The most classic use is in event listening.

    <button onClick = "handle()"> Verify that </button> Handle subscribed to the onClick event. Handle is triggered when the user clicks onClickCopy the code

By the way, there are a lot of online interpretations of the observer model. Observables are implemented based on the observer pattern

Observable method definition

Basic Features:

  1. It’s a function
  2. Accept an Observer object
  3. Returns a function or object with unsubscribe
letOb = new Observable(obser => {// This function "publishes" obser.next()}) // Console. log(12) action ob.subscribe({obser => {// this function "publishes" obser.next()})next(){console.log(12)}}) note: Only subscribe is executed"Release"functionCopy the code

Observable is extended in core-js and can be used by importing “core-js/es7/ Observable”

Implement Observable methods

Easy to understand, let’s simply implement an Observable as follows

class SubscriptionObserver {
    constructor(ob, debounceTime){
        this.ob = ob || {};
        this.debounceTime = debounceTime;
        this.unSub = false;
        this.timeout = null;
    }
    next(value){
        if(! this.unSub && this.ob.next){ clearTimeout(this.timeout) this.timeout =setTimeout(() => { ! this.unSub &&this.ob.next(value); this.timeout = null; }, this.debounceTime) }else{ this.ob.next(value); }}error() {if (!this.unSub && this.ob.error){
            this.ob.error();
        }
    }
    complete() {if (!this.unSub && this.complete){
            this.ob.complete();
        }
    }
    unsubcribe(){
        this.unSub = true;
    }
}

class Observable {
    constructor(SubscriptionOb) {
        this.SubscriptionOb = SubscriptionOb;
    }
    subscribe(ob){
        this.subOb = new SubscriptionObserver(ob, this.timeout);
        return this.SubscriptionOb(this.subOb);
    }
    unsubcribe(){
        this.subOb.unsubcribe()
        return this;
    }
    debounceTime(timeout){
        this.timeout = timeout;
        returnthis; }}Copy the code

The main addition is debounceTime, in which debounceTime only executes the next method one last time in lazy time

Application of search box

Search box search is mainly to solve two problems

  1. A search cannot be triggered every time the user enters a character.
  2. The asynchronous return time of the server is inconsistent. The character searched first may be returned later than the character searched later

The following code

export default class Tudos extends React.Component {
    state = {
        text:""} // Search keyword interface searchKeyWords(text){return new Promise((resolve) => {
            setTimeout(() => {
                letlist = [{...}...]  resolve(list) }, 2000) }) } handleInput(dom) {let oba = new Observable(ob => {
            dom.oninput = e => {
                ob.next(e.target.value)
            }
        }).debounceTime(500).subscribe({
            next(value){getList(value)}
        })

    }
    render() {
        return (<div>
            <input ref = {dom => dom && this.handleInput(dom)}/>
        </div>)
    }
}

Copy the code

The next function is always executed 500 milliseconds after the user enters. This code is already implemented. The second problem is still unresolved!

The introduction of RxJS

The installation

npm i @reactivex/rxjs --save;
Copy the code

The introduction of

import * as Rx from "@reactivex/rxjs";
Copy the code

RxJS is thought of as Lodash for handling events. The first thing that comes to mind for complex event handling like this is using RxJS

For specific usage, please refer to the following official documents

The following code

export default class SimpleSortableList extends Component {
    componentDidMount() {} // Search keyword interface searchKeyWords(text){return new Promise((resolve) => {
            setTimeout(() => {
                letlist = [{...}...]  resolve(list) }, 2000) }) } handleInput(button){ Rx.Observable.fromEvent(button,'input')
        .debounceTime(500)
        .switchMap(e => {
            return Rx.Observable.create(ob => {
                this.searchKeyWords(e.target.value).then(res => {
                    ob.next(list)
                })
            });
        })
        .subscribe(text => console.log(text))
    }
    render() {
        return( <div className={prefix}> <input ref = { dom => dom && this.handleInput(dom)} /> </div> ); }}Copy the code
  1. Delay the return of results by debounceTime
  2. Discard a result that was not returned in time by switchMap
  3. And the whole code is so short and snappy