【问题标题】:RxJs - last request with intervalRxJs - 有间隔的最后一个请求
【发布时间】:2017-04-05 00:19:28
【问题描述】:

我想知道如何在 RxJS 中获得类似下面的内容。

  1. 每隔一个请求就会发送到服务器。
  2. 响应可能需要不同的时间。 (1s以上澄清)
  3. 但是当只有一些响应到达时,所有较旧的未完成请求都将被取消,订阅将只收到这个最新完成的请求的结果。

看起来 switchMap 无法按我的意愿工作。因为每个下一个开始的请求都会在其响应之前取消前一个请求。请参阅下面的代码。

let counter = 0;
let times = [1200, 500];

let getSomePromise = function() {
  return new Promise((resolve) => {
    let i = counter;
    counter++;
    
    if (i < 2) {
      console.log('promise ' + i + ' start');
    }
    
    setTimeout(() => {
      if (i < 2) {    
        console.log('promise ' + i + ' finish');
        resolve(i);
      }
    }, times[i]);
  });
}


let ob = Rx.Observable.interval(1000)
  .switchMap(() => {
     return getSomePromise();
  });

let sub = ob.subscribe((value) => {
  console.log('result ' + value);
});
&lt;script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"&gt;&lt;/script&gt;

我明白了:

promise 0 start
promise 1 start
promise 0 finish
promise 1 finish
result 1

我想要:

promise 0 start
promise 1 start
promise 0 finish
result 0
promise 1 finish
result 1

谢谢。

【问题讨论】:

    标签: javascript rxjs


    【解决方案1】:

    您可以使用mergeMap() 运算符来获得您想要的结果。该运算符订阅从其投影函数返回的所有内部 Observables 并重新发射它们的所有项目。

    但是,据我了解,您确实想使用 switchMap() 的问题(第 3 点准确描述了 switchMap 的作用),但您的预期输出看起来像您想要的 mergeMap()

    查看更新后的代码及其输出:

    let counter = 0;
    let times = [1200, 500];
    
    let getSomePromise = function() {
      return new Promise((resolve) => {
        let i = counter;
        counter++;
        
        if (i < 2) {
          console.log('promise ' + i + ' start');
        }
        
        setTimeout(() => {
          if (i < 2) {    
            console.log('promise ' + i + ' finish');
            resolve(i);
          }
        }, times[i]);
      });
    }
    
    
    let ob = Rx.Observable.interval(1000)
      .mergeMap(() => {
         return getSomePromise();
      });
    
    let sub = ob.subscribe((value) => {
      console.log('result ' + value);
    });
    &lt;script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"&gt;&lt;/script&gt;

    【讨论】:

    • 仍然不是我需要的。如果第一个承诺在第二个承诺之后很少被解决,那么订阅永远不会得到第一个承诺的结果!
    • 那么你在你的问题中想要的输出是不正确的,对吧?你永远不应该收到result 0
    • 这是正确的,因为第二个请求还没有完成。我想根据请求发送顺序获得最新的可能结果。两种情况: 1. 如果第二个承诺作为第一个完成,我只想要它的结果,以前请求的每个结果都已过时,所以我不需要它们。 2.如果第一个promise完成了,我想在订阅中得到它的结果,并且仍然等待下一个请求的结果。
    【解决方案2】:

    您正在寻找.switchMap 运算符。

    Rx.Observable.interval(1000)
    .switchMap(() => Rx.Observable.ajax(someUrl))
    .subscribe(val => console.log(val));
    

    【讨论】:

      猜你喜欢
      • 2019-01-16
      • 2019-08-12
      • 2021-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      • 2018-02-16
      相关资源
      最近更新 更多