rxjs 技巧

skip rxjs

忽略前两次执行
skip(2)

星号背后的意义*

<h1 *myNgIf>
    Angular rocks
</h1>
等价
<ng-template myNgIf>
	<h1>
           Angular rocks 
    </h1>
</ng-template>

写个小案例

export class MyNgIfDirective implements OnInit {
  @Input() appMyNgIf: boolean = false;
    
  constructor(
    private view: ViewContainerRef,
    private template: TemplateRef<any>
  ) {}
    
  ngOnChanges() {
    if (this.appMyNgIf) {
      this.view.createEmbeddedView(this.template);
    } else {
      this.view.clear();
    }
  }
}

BehaviorSubject

需要一个初始值并将当前值发送给新订阅者

subject = new BehaviorSubject(123);

this.subject.subscribe(console.log); // 123, 345
this.subject.next(345);

// 给个值,然后修改初始值
  subject = new BehaviorSubject<any>('3333');
    let a=this.subject.asObservable();
	a.next(10);
	a.subscribe(console.log) // 10

区别

let beSub = new BehaviorSubject<number>(0); // 默认就返回初始化的值
    beSub.subscribe(console.log) // 默认 0

 let sub=new Subject();
    sub.next(1);
    sub.subscribe(console.log);// 2
    sub.next(2)

ReplaySubject

以发送旧值给新的订阅者,但是不仅是‘当前值’,还可以是之前的旧值。

// 最后4次的值  
subject: ReplaySubject<any> = new ReplaySubject<any>(4);

    this.subject.next(2);
    this.subject.next(3);
    this.subject.next(4);
    this.subject.next(5);
    this.subject.next(6);
    this.subject.next(7);
    let a=this.subject.asObservable();
    a.subscribe(console.log) // 4,5,6,7

AsyncSubject

只有当 Observable 执行完成时(执行 complete()),它才会将执行的最后一个值发送给观察者。

  private subject: AsyncSubject<number> = new AsyncSubject<number>();

    this.subject.next(2);
    this.subject.next(3);
    this.subject.next(4);
    this.subject.next(5);
    this.subject.next(6);
    this.subject.complete();
    this.subject.next(7);
    let a=this.subject.asObservable();
    a.subscribe(console.log) // 6

tap

  • tap操作符确实为使用它的每个项目运行回调,用于副作用,但返回一个与源相同的 observable。

  • 也可以用作注释,比如打印下每项做了哪些操作

const objects = [
      { id: 1, name: 'Fabian' },
      { id: 2, name: 'Jan-Niklas' },
    ];
    from(objects).pipe(tap(item=>(item.name=item.name+'xxx'))).subscribe(console.log)
//   { id: 1, name: "Fabian_2" }
//   { id: 2, name: "Jan-Niklas_2" }

Map

应用于源 Observable 发出的每个值,并将结果值作为 Observable 发出。

 const objects = [      {id: 1, name: 'Fabian'},      {id: 2, name: 'Jan-Niklas'},    ];from(objects).pipe(map(v => v.id + 1)).subscribe(console.log)

MapTo

我觉得应用就是类似于请求超时

// delay 模拟请求延时of(1).pipe(delay(1000),mapTo('失败')).subscribe(console.log)

concat concatMap

concat(of(1),of(2),of(3)).subscribe(console.log)// 1,2,3of(1,'a').pipe(concatMap(v => of(v+'a'))).subscribe(console.log)// 1a,aa

同步的情况下concat===merge

异步用merge

const a=interval(1000).pipe(map(v => v * 100));
const b=interval(2000).pipe(map(v => v * 1000));
concat(a,b).pipe(take(10)).subscribe(console.log)
我们发现b一直不执行,因为是同步的

    concat(interval(1000).pipe(map(v => v * 100)),interval(2000).pipe(map(v => v * 1000))).pipe(take(10)).subscribe(console.log)
// 我们发现是交错执行的

switchMap、mergeMap、concatMap和exhaustMap 区别

 // 模拟异步请求
    const prepOrder = (order: string) => {
      const delayTime = Math.floor(Math.random() * 100);
      return of(order).pipe(delay(delayTime))
    };

from(['aaa', 'bbb', 'ccc', 'ddd']).pipe(
      //异步展示
      // mergeMap(v => prepOrder(v))
      //同步展示
      // concatMap(v => prepOrder(v))
      // 只对最后一次有响应
      // switchMap(v=>prepOrder(v))
      // 只对第一次有响应
      exhaustMap(v=>prepOrder(v))
    ).subscribe(console.log)

from([1,2,3]).pipe(mergeMap(v=>of(v).pipe(delay(500)))).subscribe(console.log)
// 1,2,3
from([1,2,3]).pipe(switchMap(v=>of(v).pipe(delay(500)))).subscribe(console.log)
// 3
from([1,2,3]).pipe(exhaustMap(v=>of(v).pipe(delay(500)))).subscribe(console.log)
// 1

-🤯 mergeMap:我是一个勤奋的人,我可以同时准备多个订单!但我不尊重订单顺序。

-😇 concatMap:我尊重订单顺序!一旦我完成我目前正在做的事情,你就会得到你的订单。

-🙄exhaustMap 我已经筋疲力尽了!当我准备订单时,我不会听任何其他订单。

-😈 switchMap:我是说!如果我收到新的订单,您的订单将被丢弃。

@Input

_vName:string;
@Input()
get vName(){
    return this._vName
}
set vName(name:string){
    this._vName=name;
}

async

num=of(1);

<h1 *ngIf="num|async as date1">{{date1}}</h1>

多个api请求

 prepOrder(order: string | number) {
    const delayTime = Math.floor(Math.random() * 100);
    return of(order).pipe(delay(delayTime))
  };

 from([1, 2, 3, 4]).pipe(
     // 模拟请求
      mergeMap(item => this.prepOrder(item)),
     // 让一个个请求
      concatMap(item => of(item).pipe(delay(1000)))
    ).subscribe(console.log);

angular 最新版

npx @angular/cli  new xxx

promise=> observable

  from(new Promise(res=>res('xxx'))).subscribe(console.log)
// xxx

share() 多播

没加share()
let a = interval(1000).pipe(map(x => {
        console.log('测试'+x);
        return x * x
      }),
      take(2),
    )


a.subscribe(v=>{
      console.log('sub1-' + v);
    })
a.subscribe(v=>{
      console.log('sub2-' + v);
    })
// 测试0
// sub1-0
// 测试0
// sub2-0
// 测试1
// sub1-1
// 测试1
// sub2-1
加入
pipe(map(x => {
        console.log('测试'+x);
        return x * x
      }),
      take(2),
      share()
    )
// 测试0
// sub1-0
// sub2-0
// 测试1
// sub1-1
// sub2-1

NEVER

则是返回一个永不完结的Observable,不会调用观察者的任何函数

NEVER.subscribe(() => {
      console.log('执行');
    }, console.log, () => {
      console.log('执行了--');
    });

EMPTY

EMPTY是直接返回一个完成的Observable,会直接调用观察者的completed函数

  throwError('error').pipe(
      catchError(() => {
        return EMPTY
      })
    ).subscribe(() => {
      console.log('执行');
    }, console.log, () => {
      console.log('执行了--');
    });
// 执行了--

repeatWhen

repeat能够重复订阅上游的Observable,但是不能控制订阅时间,如等待 2 秒再重新订阅

 of(1, 2, 3).pipe(
      repeatWhen(v => v.pipe(delay(2000))),
      take(8)
    ).subscribe(console.log)

concat和 merge

    let a = timer(2000).pipe(mapTo('TO1'));
    let b = timer(1000).pipe(mapTo('TO2'));
    merge(a, b).subscribe(console.log);
	// To2	To1, 异常
	concat(a,b).subscribe(console.log)
	// To1	To2  同步

   of(1, 2).pipe(
      // mergeMap(v => [a, b][v - 1])
      concatMap(v => [of(1),of(2)][v - 1])
    ).subscribe(console.log);

zip

    zip(of('a','b','c'),of(1,2,3),of('v','x','y')).subscribe(console.log)
 // ['a', 1, 'v']
// ['b', 2, 'x']
//  ['c', 3, 'y']

let age$ = of(27, 25, 29);
let name$ = of('Foo', 'Bar', 'Beer');
let isDev$ = of(true, true, false);
 
zip(age$, name$, isDev$).pipe(
  map(([age, name, isDev]) => ({ age, name, isDev }))
)
.subscribe(x => console.log(x));
 
// { age: 27, name: 'Foo', isDev: true }
// { age: 25, name: 'Bar', isDev: true }
// { age: 29, name: 'Beer', isDev: false }

zipAll

const source1 = of(1,2,3);
const source2 = of('a','b','c');

of(source1, source2)
  .pipe(zipAll())
  .subscribe(val => console.log(val));
// [1, 'a']
// [2, 'b']
// [3, 'c']

JorkJoin

当所有 observable 完成后,从每个 observable 发出最后发出的值。

    const myPromise = (val: string) =>
      new Promise(resolve =>
        setTimeout(() => resolve(`Promise Resolved: ${val}`), 2000)
      );

    // 一组observable值 只关心每个的最终发出值
    forkJoin({
      my1: myPromise('my1'),
      my2: myPromise('my2'),
    }).subscribe(console.log)

// {my1: 'Promise Resolved: my1', my2: 'Promise Resolved: my2'}

ngIf /then

<div *ngIf="list | async as items;then list1"></div><ng-template #list1 let-items>  <div *ngFor="let item of items">{{item}}</div></ng-template>of([1,2,3,4])
posted @ 2021-09-30 15:18  猫神甜辣酱  阅读(124)  评论(0编辑  收藏  举报