Four other implementations of RxJS
The cause of
The reason why I think of this library is that I saw the Callbag library. You can find the principle of the Callbag library by yourself. I will not repeat it, but I will talk about my understanding. Callbag is designed to combine consumers and producers into one and communicate by passing a callback function to each other. For those of you who have seen how some of these operators work, the logic must be very difficult to understand, because you are running out of brain circuits with too many callbacks. After I used some library functions, I realized that there was no need for such a complicated design. Why? See below
Much the same callbag
There is a lot of code in callbag is written repeatedly, the reason is very simple, the function is determined, such as subscription function, this is essential operation, let me compare my library implementation and callbag implementation.
Compare to implement producer interval
Callbag source code first
const interval = period= > (start, sink) => {
if(start ! = =0) return;
let i = 0;
const id = setInterval((a)= > {
sink(1, i++);
}, period);
sink(0, t => {
if (t === 2) clearInterval(id);
});
};
export default interval;
Copy the code
explain
if(start! =0)return
Copy the code
This sentence can be found everywhere in the Callbag implementation library. It is because of this sentence that I think, why do I repeat it every time? Of course, because this is a producer, it only sends data, it doesn’t receive data.
sink(0, t => {
if (t === 2) clearInterval(id);
});
Copy the code
The above code actually implements an unsubscribe function by passing back a callback to the passed callback, which will probably burn your brain.
The interval observable prototype above represents most callbag cases, so is there a way to implement it in a more concise way?
ShowTime
exports.interval = period= > n => {
let i = 0;
const id = setInterval((a)= > n(i++), period)
return (a)= > clearInterval(id)
}
Copy the code
What, just a few lines of code? Yes, this is the library that I think has the smallest implementation code. This code is small, high-performance, and easy to understand. Of course, I have to explain a little bit that in order for interval(1000) to be a real producer, you have to be able to subscribe, you have to be able to unsubscribe, and you have to be able to get the data that the producer sends (some of which also need to get complete and error events, Interval will not complete or error.
interval(1000)
I’m going to get a functionN = >...
, which takes a next function to send data- call
interval(1000)
This higher-order function is equivalent to “subscribe”, which is important here (instead of sending type 0 in callbag) - Dispose (instead of a callbag that returns a callback and accepts type 2)
- The incoming next function n is called, and the data is sent
Of course interval doesn’t work on its own, we need more operators and observers to make the library work.
The filter comparison operator
Here is the implementation of callbag
const filter = condition= > source => (start, sink) = > {
if(start ! = =0) return;
let talkback;
source(0, (t, d) => {
if (t === 0) {
talkback = d;
sink(t, d);
} else if (t === 1) {
if (condition(d)) sink(t, d);
else talkback(1);
}
else sink(t, d);
});
};
module.exports = filter;
Copy the code
It still shows up
if(start! =0)return
Copy the code
Yes, because the filter is only used to be subscribed, and is itself a data responder, some people say no, the filter needs to respond to the source at the upper level, yes, so you need to subscribe to the source at the upper level, but instead of passing in itself, you need another callback function to respond, otherwise there will be a problem. The core code is one sentence, but it needs a lot of code to keep it running, and I can’t watch it anymore.
ShowTime
exports.filter = f= > source => (n, c) = > source(d= > f(d) && n(d), c)
Copy the code
What? One line of code? You read that right! You read that right! You read that right! So let me explain this line of code. Filter is the operator, filter(d=>d>1) means I only accept data greater than 1. This will return source=>… This function accepts a source as the upper-level data source, either as a producer like interval(1000) above, or as another operator. so
const obserable = filter(d= > d > 1)(interval(1000))
Copy the code
You will get a (n,c)=>… You can pass in the next function n and the complete function C to “subscribe”
const disposable = obserable(d= > console.log('get',d),err => console.log('complete'))//err indicates an error
Copy the code
When you subscribe, you get a function called Disposable, which is used to unsubscribe.
disposable()// Unsubscribe
Copy the code
This filter represents the essence of the minimum library: Disposable can be returned all the way from the arrow function. It is implicit in the filter, and the C function representing complete is also directly passed through without any changes. The only thing that needs to be done is the next function, and you need to pass a new next function to the source. Send data to the next function at the next level when the condition is met, otherwise do nothing.
(To be continued)