• RxJS操作符(二)


    take()自动取消订阅,可以终止Observable和Observe之间的订阅关系。

    一、Observable的性质

    三种状态:nex, error, complete

    进入到Error状态:

    const interval$ = Rx.Observable.interval(1000)
    .filter(val=>{
      throw '出错了'
    })
    .take(4)
    .reduce((x,y)=>{//reduce接收函数作为参数
      return [...x,y];
    },[])
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.error('Error:' + err),
      ()=>console.log('I am complete')
    );

    二、特殊类型的Observable

    • 永不结束
    • Never
    • Empty
    • Throw

    永不结束:没有complete状态,比如计时器,每隔1s发射item。

    Never:完全不发射item,也不结束。【测试时帮助构成条件】

    const interval$ = Rx.Observable.never();
    //不会emit任何元素,也不会结束
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.error('Error:' + err),
      ()=>console.log('I am complete')
    );
    View Code

    Empty:流里没有元素,直接进入Complete状态。

    const interval$ = Rx.Observable.empty(); //不会输出任何元素,直接结束
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.error('Error:' + err),
      ()=>console.log('I am complete')
    );
    View Code

    Throw:不发生任何东西,直接进入Error状态。 

    const interval$ = Rx.Observable.throw('出错了');
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.error('Error:' + err),
      ()=>console.log('I am complete')
    );
    View Code

    三、工具类操作符do

    一般用来做调试。

    或者外部条件的设置。

    流进入到下一步之前需要对外部的东西进行改变【写文件之类】

    const interval$ = Rx.Observable.interval(1000)
    .map(val=>val*2)
    .do(v=>console.log('val is' +v))   //在map之后,take之前,在流发生之前看一下流里有什么东西
    .take(3);
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

    do很像临时subscribe,但是没有把流中断掉。可以继续应用操作符。临时中间桥梁,打印值做调试。

    let logLabel='当前值是';
    
    const interval$ = Rx.Observable.interval(1000)
    .map(val=>val*2)
    .do(v=>{
           console.log(logLabel +v); //取得了外部的值
           logLabel='当前'; //改变了外部的值
    })
    .take(4);
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

     

    四、变换类操作符:scan

    scan:

    场景:记住之前的运算结果。每次运算都会发射值。

    scan接收函数作为参数,x是增加器,默认初始值0,把函数返回的结果作为下次的x。

    const interval$ = Rx.Observable.interval(1000)
    .filter(val=>val%2===0)
    .scan((x,y)=>{//scan接收函数作为参数
      return x+y;
    })
    .take(4)
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

    五、数学类操作符reduce

    数组中也有,使用比较频繁。

    和scan对比,reduce只会发射一个最终值。

    .filter(val=>val%2===0)
    .take(4)
    .reduce((x,y)=>{//reduce接收函数作为参数,只会发射一个最后的值
      return x+y;
    })
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

    高级用法:

    const interval$ = Rx.Observable.interval(1000)
    .filter(val=>val%2===0)
    .take(4)
    .reduce((x,y)=>{//reduce接收函数作为参数
      return [...x,y];  //每次数组加y
    },[]) //x初始值为空数组[]
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

    六、过滤类操作符 filter,take,first/last,skip...

    总共100多种operator。

    filter:

    let logLabel='当前值是';
    
    const interval$ = Rx.Observable.interval(1000)
    .filter(val=>val%2===0)  //过滤偶数
    .do(v=>{console.log(logLabel +v);
           logLabel='当前';}
    )
    .take(3);
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

    first:

    const interval$ = Rx.Observable.interval(1000)
    .filter(val=>val%2===0)
    .first()    //和take(1)是一样的,取第一个
    // .take(1) 
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

    skip: 和take相反

    const interval$ = Rx.Observable.interval(1000)
    .filter(val=>val%2===0)
    .skip(2); //过滤掉0和2
    
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    ); 

    用skip和take就能做到分页的效果。

    七、常见创建类操作符:Interval,Timer

    1、interval

    const interval$ = Rx.Observable.interval(1000);
    interval$.subscribe(val=>console.log(val));

    通过take取前3个来看三种状态的效果

    const interval$ = Rx.Observable.interval(1000).take(3);
    interval$.subscribe(
      val=>console.log(val),
      err=>console.log(err),
      ()=>console.log('I am complete')
    );

    2、Timer

    const timer$= Rx.Observable.timer(1000);
    
    timer$.subscribe(v=>console.log(v));
    //控制台只输出一个值0

    第一个参数:delay多长时间

    第二个参数:之后要以什么频率发送

    const timer$= Rx.Observable.timer(1000,1000);
    timer$.subscribe(v=>console.log(v));
    //类似interval,但是interval不能指定开始延迟时间

    实践:给Observable增加一个debug操作符

    只有在生产环境才输出

    import {Observable} from 'rxjs/Observable';
    import {environment} from '../../environments/environment';
    
    declare module 'rxjs/Observable' {
      interface Observable<T> {
        debug: (...any) => Observable<T>;
      }
    }
    
    Observable.prototype.debug = function(message: string) {
      return this.do(
        (next) => {
          if (!environment.production) {
            console.log(message, next);
          }
        },
        (err) => {
          if (!environment.production) {
            console.error('ERROR>>>', message, err);
          }
        },
        () => {
          if (!environment.production) {
            console.log('Completed - ');
          }
        }
      );
    };

    本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:https://www.cnblogs.com/starof/p/9137865.html 有问题欢迎与我讨论,共同进步。

  • 相关阅读:
    Bullet 学习笔记之 btPersistentManifold 及 btManifoldPoint
    Bullet 学习笔记之 btCollisionWorld::performDiscreteCollisionDetection
    Bullet 学习笔记之 btCollisionWorld
    hdu 6617
    codeforces 1247 E
    GYM 101174 A
    GYM 100714 G
    codeforces 1239 C
    牛客挑战赛33D
    codeforces 1238 E
  • 原文地址:https://www.cnblogs.com/starof/p/9137865.html
Copyright © 2020-2023  润新知