zoukankan      html  css  js  c++  java
  • RxJS---转载

    摘自 此处:https://segmentfault.com/a/1190000012252368

    导入方式

    避免使用 import { Observable } from 'rxjs'这种方式导入,这会导入整个rxjs库,按需导入的方式如下:
    import { Observable } from 'rxjs' //导入类

    RxJS团队设计了以下规则来帮助JavaScript开发人员重构import路径:

    • rxjs: 包含创建方法,类型,调度程序和工具库。

      import { Observable, Subject, asapScheduler, pipe, of, from, interval, merge, fromEvent } from 'rxjs';
    • rxjs/operators: 包含所有的管道操作符

      import { map, filter, scan } from 'rxjs/operators';
    • rxjs/webSocket: 包含websocket subject实现.

      import { webSocket } from 'rxjs/webSocket';
    • rxjs/ajax: 包含Rx ajax实现.

      import { ajax } from 'rxjs/ajax';
    • rxjs/testing: 包含RxJS的测试工具库.

      import { TestScheduler } from 'rxjs/testing';

    subscribe

    subscribe完整的函数签名如下:

    ob.subscribe({
        next: d => console.log(d),
        error: err => console.error(err),
        complete: () => console.log('end of the stream')
    })

    直接给subscribe传入一个函数会被当做是next函数。这个完整的包含3个函数的对象被称为observer(观察者),表示的是对序列结果的处理方式。

    • next表示数据正常流动,没有出现异常;
    • error表示流中出错,可能是运行出错,http报错等等;
    • complete表示流结束,不再发射新的数据。在一个流的生命周期中,errorcomplete只会触发其中一个,可以有多个next(表示多次发射数据),直到complete或者error

    创建可观察序列

    点击此处查看示例

    Observable.of(...args)

    Observable.of()可以将普通JavaScript数据转为可观察序列

    Observable.fromPromise(promise)

    Promise转化为Observable

    Observable.fromEvent(elment, eventName)

    DOM事件创建序列,例如Observable.fromEvent($input, 'click')

    Observable.ajax(url | AjaxRequest)

    发送http请求,AjaxRequest

    Observable.create(subscribe)

    这个属于万能的创建方法,一般用于只提供了回调函数的某些功能或者库,在你用这个方法之前先想想能不能用RxJS上的类方法来创建你所需要的序列

    合并序列

    const ob1 = Observable.ajax('api/detail/1');
    const ob2 = Observable.ajax('api/detail/2');
    ...
    const obs = [ob1, ob2...];// 分别创建对应的HTTP请求。
    • N个请求按顺序串行发出(前一个结束再发下一个)

    Observable.concat(...obs).subscribe(detail => console.log('每个请求都触发回调'));

    • N个请求同时并行发出,对于每一个到达就触发一次回调
      Observable.merge(...obs).subscribe(detail => console.log('每个请求都触发回调'));
    • N个请求同时发出并且要求全部到达后合并为数组,触发一次回调
    Observable.forkJoin(...obs).subscribe(detailArray => console.log('触发一次回调'));
    

     

    使用RxJS实现搜索功能

    搜索是前端开发中很常见的功能,一般是监听<input />keyup事件,然后将内容发送到后台,并展示后台返回的数据。

    var text = document.querySelector('#text');
    var inputStream = Rx.Observable.fromEvent(text, 'keyup') //为dom元素绑定'keyup'事件
                        .debounceTime(250) // 防抖动(防止重复的请求)
                        .pluck('target', 'value') // 取值
                        .switchMap(url => Http.get(url)) // 将当前输入流替换为http请求
                        .subscribe(data => render(data)); // 接收数据

     RxJS能简化你的代码,它将与流有关的内部状态封装在流中,而不需要在流外定义各种变量来以一种上帝视角控制流程。

    一些操作符

    合并 forkJoin, merge, concat
    创建 of, from, fromPromise, fromEvent, ajax, throw
    实例操作符(对流中的数据进行处理或者控制流程)
    map, filter,switchMap, toPromise, catch, take, takeUntil, timeout, debounceTime, distinctUntilChanged, pluck

    Map与switchmapflatmap

    let stream = Observable.interval(1000).take(10);
    return stream.map(n => Observable.timer(500).map(() => n));

    这里stream会返回一个Observable而不是数字。

    如果我想要拿到那些数字,我该怎么办?

    let stream = Observable.interval(1000).take(10);
    return stream.flatMap(n => Observable.timer(500).map(() => n));

    这里使用了flatMap而不是mapflatMap将响应数据“打平”,也就是说把映射后新的Observable转化为了数据流,订阅之后会获得这个新Observable发射的数据,而不是Observable本身。

    译者注:flatMap有一个很适用的场景,就是搜索框。在用户输入一串字符后,将其发送到服务器并获取搜索结果,这里就涉及到两个Observable

    Observable
    .fromEvent($input, 'keyup')
    .flatMap(text => getHttpResponse(text))
    .subscribe(data => console.log(data))

    使用flatMap就可以直接获取到新的Observable返回的数据。但是这里存在一个问题,如果用户有多次输入,由于网络原因可能会发生前一次响应时间比后一次长的情况,这时后一次的结果就被覆盖了。
    flatMapLatest可以解决这个问题。如果之前的Observable还没有未触发,而又收到了新的ObservableflatMapLatest会取消之前的Observable,只处理最新收到的Observable,这样就保证了处理请求的先后顺序,flatMapLatestRxJS 5.x中已更名为switchMap

    forkJoin, zip, combineLatest之间的区别

    forkJoin

    forkJoin合并的流,会在每个被合并的流都发出结束信号时发射一次也是唯一一次数据。假设我们有两个流:

    1 const ob1 = Rx.Observable.interval(1000).map(d => `ob1:${d}`).take(3);
    2 const ob2 = Rx.Observable.interval(2000).map(d => `ob2:${d}`).take(2);
    3 
    4 Rx.Observable.forkJoin(ob1, ob2).subscribe((data) => console.log(data));
    5 // ["ob1:2", "ob2:1"]

    ob1会在发射完第三个数据时停止发射,ob2会在发射完第二个数据时停止,而forkJoin合并后的流会等到ob1ob2都结束时,发射一次数据,也就是触发一次subscribe里的回调,接收到的数据为ob1ob2发射的最后一次数据的数组。

    zip

    zip工作原理如下,当每个传入zip的流都发射完毕第一次数据时,zip将这些数据合并为数组并发射出去;当这些流都发射完第二次数据时,zip再次将它们合并为数组并发射。以此类推直到其中某个流发出结束信号,整个被合并后的流结束,不再发射数据。

    const ob1 = Rx.Observable.interval(1000).map(d => `ob1:${d}`).take(3);
    const ob2 = Rx.Observable.interval(2000).map(d => `ob2:${d}`).take(2);
    
    Rx.Observable.zip(ob1, ob2).subscribe({
      next: (data) => console.log(data),
      complete: () => console.log('complete')
    });
    // ["ob1:0", "ob2:0"] ob1等待ob2发射数据,之后合并
    // ["ob1:1", "ob2:1"] 此时ob2结束,整个合并的流也结束
    // "complete"
     

    zipforkJoin的区别在于,forkJoin仅会合并各个子流最后发射的一次数据,触发一次回调;zip会等待每个子流都发射完一次数据然后合并发射,之后继续等待,直到其中某个流结束(因为此时不能使合并的数据包含每个子流的数据)。

    combineLatest

    combineLatestzip很相似,combineLatest一开始也会等待每个子流都发射完一次数据,但是在合并时,如果子流1在等待其他流发射数据期间又发射了新数据,则使用子流最新发射的数据进行合并,之后每当有某个流发射新数据,不再等待其他流同步发射数据,而是使用其他流之前的最近一次数据进行合并。

    const ob1 = Rx.Observable.interval(1000).map(d => `ob1:${d}`).take(3);
    const ob2 = Rx.Observable.interval(2000).map(d => `ob2:${d}`).take(2);
    
    Rx.Observable.combineLatest(ob1, ob2).subscribe({
      next: (data) => console.log(data),
      complete: () => console.log('complete')
    });
    // ["ob1:1", "ob2:0"] ob1等待ob2发射,当ob2发射时ob1已经发射了第二次数据,使用ob1的第二次数据
    // ["ob1:2", "ob2:0"] ob1继续发射第三次也是最后一次数据,ob2虽然还未发射,但是可以使用它上一次的数据
    // ["ob1:2", "ob2:1"] ob2发射第二次也是最后一次数据,使ob1上一次的数据。
    // "complete"
     
    由于无法解释的神圣旨意,我们徒然地到处找你;你就是孤独,你就是神秘,比恒河或者日落还要遥远。。。。。。
  • 相关阅读:
    linuxc查看进程命令
    Springboot+post请求接口
    Springboot+get请求接口
    xml 加载多个properties文件
    TCP的三次握手(建立连接)和四次挥手(关闭连接)
    记一次 synchronized 锁字符串引发的坑兼再谈 Java 字符串
    java单点登录原理与简单实现
    关于 Java 面试,你应该准备这些知识点
    Java 内存模型
    java利用SuffixFileFilter统计目录下特定后缀名文件的数目
  • 原文地址:https://www.cnblogs.com/momoli/p/13824579.html
Copyright © 2011-2022 走看看