英文资源
-
Learn RxJS operators and Reactive Programming principles: https://reactive.how/
-
Animated playground for Rx Observables: https://rxviz.com/
中文资源
-
中文笔记整理: http://rx.js.cool/
-
中文文档: https://cn.rx.js.org/
实用库
- https://www.npmjs.com/package/v0
- Rxjs Wrapper for Redis: https://www.npmjs.com/package/rxdis
在 Nest.js 中使用
在 Controllers / Services 中使用:
import { Controller, Get } from '@nestjs/common';
import { from, Observable } from 'rxjs';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): Observable<number> {
// return this.appService.getHello();
return from(Promise.resolve(10));
}
}
在 Mongoose 中使用
Rx.Observable that can sequentially pull data from a mongoose (mongodb) cursor with fine control over concurrency
import { Observable } from 'rxjs';
// This took me way too long to figure out. Hope this helps someone.
// <3 Well Caffeinated
function fromCursor( cursor ){
return new Observable((obs) => {
// is the connection closed
var closed = false
// get the next document
function getNext(){
return cursor.next((err, doc) => {
if ( err ){
return obs.error( err )
}
if ( !doc ){
// no document so we're done
return obs.complete()
}
// call next, however we'll pass it an observable
// that way we delay fetching the next document until
// the current one is observed
obs.next(Rx.Observable.defer( () => {
if ( !closed ){ getNext() }
return Rx.Observable.of(doc)
}))
})
}
// start
getNext()
// cleanup
return () => {
closed = true;
cursor.close();
}
})
}
usage example:
const Model = require('some/mongoose/model')
const taskFn = require('some/task/fn')
function performMaintenance( concurrency = 1 ){
let query = Model.find({ needsMaintenance: true })
// this will return an observable stream of the result of taskFn
return fromCursor( query.cursor() ).mergeMap( obs => {
// we use mergeMap because we want to perform async tasks on each document
// we need to use flatMap because we're receiving an observable, not the document!
// taskFn could return an observable, or a promise
return obs.flatMap( doc => taskFn(doc) )
}, concurrency)
}
// do stuff
performMaintenance( 2 ).subscribe({
next: ( result ) => console.log('updated document', result)
, error: ( err ) => console.error( err )
, complete: () => console.log('done')
})
示例
方便灵活地数据过滤
import { from, iif, Observable, of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
type Cat = {
name: string;
age: number;
};
function filter({ age = '', name = '' }: { age?: string; name?: string } = {}): Observable<Cat[]> {
return (
from(
Promise.resolve([
//
{ age: 1, name: 's3' },
{ age: 2, name: 's2' },
{ age: 1, name: 's1' }
])
)
//
.pipe(
// 可自由增删过滤的类型
// Filter by Age
mergeMap((cats) =>
iif(
//
() => age !== '',
of(cats.filter((cat) => `${cat.age}` === age)),
of(cats)
)
),
// Filter by Name
mergeMap((cats) =>
iif(
//
() => name !== '',
of(cats.filter((cat) => cat.name === name)),
of(cats)
)
)
)
);
}
filter({
age: '1',
name: 's1'
}).subscribe(console.log);