V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
node
V2EX  ›  程序员

Rx 问题一则

  •  
  •   node · 2017-04-10 18:36:57 +08:00 · 3040 次点击
    这是一个创建于 2775 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设有一个输入源,后面接 throttle 操作符来控制输出的时间间隔,像这样

    var clicks = Rx.Observable.fromEvent(document, 'click'); var result = clicks.throttleTime(1000); result.subscribe(x => console.log(x));

    另有一路输入源是突发型的,来了之后不受 throttle 的限制,直接向后输出,并且能重置之前普通输入源在 throttle 里面的计时器,请问这个需求该怎么实现呢?

    12 条回复    2017-04-10 23:46:26 +08:00
    jackisnotspirate
        1
    jackisnotspirate  
       2017-04-10 20:06:49 +08:00 via iPhone
    不太明白,能不能讲一讲什么场景
    node
        2
    node  
    OP
       2017-04-10 20:44:28 +08:00
    @jackisnotspirate
    是要发送一个同步信息用的网络请求,一般情况下一小时请求一次就够了,采用某种同步方式来触发(比如所有的点击事件),所有一小时间隔以内的触发都屏蔽掉,但是有某个按钮在点击后必须立即发送这个网络请求,这次请求完成后,也是在之后的一个小时内屏蔽掉其它的普通触发
    SoloCompany
        3
    SoloCompany  
       2017-04-10 21:36:02 +08:00
    var buttonA = ...
    Rx.Observable.fromEvent(document, 'click')
    .throttle(ev => Rx.Observable.interval(ev.source = buttonA ? 0 : 1000))
    .subscribe(x => console.log(x));
    node
        4
    node  
    OP
       2017-04-10 21:55:06 +08:00
    @SoloCompany
    好像不行,这个 interval 只能设定往后时间的定时器,也就是说普通触发往后一秒无论如何都会被锁死,普通的和特殊的都是,而反过来特殊触发之后的任何触发都会被接受,也是普通的和特殊的都是
    jackisnotspirate
        5
    jackisnotspirate  
       2017-04-10 22:01:58 +08:00   ❤️ 1
    ```
    Rx.Observable.interval(1000).takeUntil(
    Rx.Observable.fromEvent(document, 'click')
    .throttle
    .flatMapLatest (Rx.Observable.interval(1000))
    )
    ```
    jackisnotspirate
        6
    jackisnotspirate  
       2017-04-10 22:05:04 +08:00   ❤️ 1
    先建一个定时器,然后每次点击会产生一个新的定时器,废掉最开始的定时器, takeUntil 是从 RxSwift 里面找的, Emits elements from a source Observable sequence until a reference Observable sequence emits an element.
    你可以看下对应功能 RxJS 里面的 operator 。 代码你要修改一下,只是大概表达一下思路
    node
        7
    node  
    OP
       2017-04-10 22:46:40 +08:00
    @jackisnotspirate
    非常感谢啊,这样说起来的确有些思路了,但是废立定时器和 throttle 怎么结合还是有点不明白,能再具体些吗?
    SoloCompany
        8
    SoloCompany  
       2017-04-10 22:52:31 +08:00   ❤️ 1
    @node 可以用 sample ,和 throttle 的差别是一个是定时触发,另一个是阀门(触发时间接近严格等于事件源时间)

    先建一个可干预的定时器

    var timer = new Rx.Subject();
    Rx.Observable.interval(1000).subscribe(timer); // 每秒触发一次
    Rx.Observable.fromEvent(buttonA, 'click').subscribe(timer); // button A 按下也触发一次

    // 用这个可干预的定时器来控制事件触发频率
    var result = timer.sample(Rx.Observable.fromEvent(document, 'click'));
    result.subscribe(x => console.log(x));
    SoloCompany
        9
    SoloCompany  
       2017-04-10 23:00:41 +08:00   ❤️ 1
    还是有一点小问题,但不难修正
    就是让 buttonA 按下的同时,不但要给 timer 推一个事件
    还要 unsubscribe 掉之前的计时器, 重新 subscribe 一个新的计时器
    以确保时钟要重新计算
    jackisnotspirate
        10
    jackisnotspirate  
       2017-04-10 23:07:38 +08:00   ❤️ 1
    @node takeUnti 相当于废掉最先的那个 Rx.Observable.interval(1000), flatMapLatest 会废掉这次 click 之前,也就是上一次 click 生成的 timer (这个 timer 能马上执行一次,并间隔执行,需要自己替换), throttle 只是改变了 click 生成 timer 的频率,跟废除 timer 没关系
    NxiJSiOS
        11
    NxiJSiOS  
       2017-04-10 23:31:25 +08:00
    @jackisnotspirate RxSwift 大神?
    node
        12
    node  
    OP
       2017-04-10 23:46:26 +08:00
    @SoloCompany
    嗯,谢谢,不过最好能一气呵成,更 rx 些,其实考虑 unsubscribe 的话,直接在特殊触发后废立一次 subscription 就好了

    @jackisnotspirate
    请问能用代码演示一下吗?因为之前的代码里没有出现特殊触发事件,假设普通触发是 fromEvent(buttonPlain, 'click'),特殊触发是 fromEvent(buttonSpecial, 'click')这样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4888 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 03:57 · PVG 11:57 · LAX 19:57 · JFK 22:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.