# fastrx

A lightweight, high-performance reactive stream library and the runtime
backend for [Rill](https://github.com/langhuihui/rill).

## Install

```bash
npm i fastrx
```

## Usage

```js
import { filter, of, pipe, subscribe } from 'fastrx';

pipe(of(1, 2, 3), filter(x => x < 2), subscribe(console.log));
```

### Rill-compatible distinct

Rill's `distinct` operator suppresses consecutive values whose selected keys
are strictly equal. The same operator is available directly from fastrx:

```js
import { distinct, pipe, subscribe } from 'fastrx';

pipe(
  users,
  distinct(user => user.id),
  subscribe(console.log),
);
```

dataflow for 1000000 source events
-----------------------------------------------

| lib   |      op/s      |  samples |
|----------|:-------------:|------:|
|rx4rx-lite  | 11.29 op/s ±  1.47%  | (56 samples)
|rx4rx-fast  | 22.56 op/s ±  1.77%  | (57 samples)
|cb-basics   |  9.56 op/s ±  1.73%  | (49 samples)
|xstream     | 5.37 op/s ±  0.68%   | (30 samples)
|most        | 17.32 op/s ±  1.93%  | (82 samples)
|rx 6        |  6.28 op/s ±  3.10%  | (35 samples)
-----------------------------------------------

#extensible

## Observable.create way

```js
import rx from 'fastrx';
const myObservable = rx(sink=>{
    sink.next('data')
    sink.complete()
})
myObservable.subscribe(console.log)
```
or

```js
import {pipe,subscribe} from 'fastrx/pipe';
const myObservable = ()=>sink=>{
    sink.next('data')
    sink.complete()
}
pipe(myObservable(), subscribe(console.log))
```

## add to library
```js
import rx from 'fastrx';
rx.myObservable = (args) => sink => {
    const id = setTimeout(()=>{
        sink.next(args)
        sink.complete()
    })
    sink.defer([clearTimeout,null,id])
    //or sink.defer(()=>clearTimeout(id))
}
```
then you can use your observable anywhere

```js
import rx from 'fastrx';
rx.myObservable('something').subscribe(console.log)
```

## vue2.0 usage
```js
import rx from "fastrx";
import RxComputed from "fastrx/vue";
Vue.use(RxComputed);

```
```html
<template>
    <div @click="onClick1" :style="{top:y+'px',left:x+'px'}">
        <span>{{test1}}</span>
        <span>{{test0}}</span>
    </div>
</template>
<script>
import rx from 'fastrx'
export default {
   rxComputed:{
       test0:()=>rx.interval(1000).take(10),//简单的订阅
       test_watch:{//使用watch触发Observable发射数据
           get:ob=>ob.switchMapTo(rx.interval(1000)).map(x=>10-x)
           watch:"test1"
       },
       test1:{//使用设置方法的方式触发，可以提供给事件回调
           get:ob=>ob.switchMap(rx.timer(1000)),
           handler:"onClick1"
       },
       test2:{
           call:true,//调用test2方法而不是设置属性
           get:ob=>ob.switchMap(e=>rx.timer(1000).map(()=>e)),
           handler:"onClick1"
       },
       "x,y":{//采用解构，将结果对象中的x,y属性分别写入vue实例中的x和y属性
            get:ob=>ob.switchMap(e=>rx.timer(1000).map(()=>({x:e.screenX,y:e.screenY}))),
           handler:"onClick1",
           default:{x:0,y:0}//设置默认值
        }
   },
   methods:{
       test2(e){
           console.log(e)
       }
   }
}
</script>
```

## vue3.0 usage
```html
<template>
    <div @click="handler"></div>
    <div>{{count}}</div>
    <div>{{count2}}</div>
</template>
<script>
import rx from 'fastrx'
export default {
    setup(){
        const ob = rx.eventHandler()
        const count =  ob.switchMapTo(rx.interval(1000)).toRef()
        const count2 = rx.watch(count).map(x=>x*2).toRef()
        return {handler:ob.handler,count,count2}
    }
}
</script>
```