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:
- It’s a function
- Accept an Observer object
- 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
- A search cannot be triggered every time the user enters a character.
- 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
- Delay the return of results by debounceTime
- Discard a result that was not returned in time by switchMap
- And the whole code is so short and snappy