RxJS:使用switchMap产生N值的背压

时间:2016-08-21 15:55:35

标签: rxjs

我正在谈论一些涉及分页的RESTful搜索端点。用户在搜索字段中键入时会触发查询,因此会生成一个带有N个值的Observable,对应于N个结果页面。

代码看起来有点像:

function runQueries(queryObservable) {
  return queryObservable
           .debounceTime(500)
           .distinctUntilChanged()
           .switchMap(search);
}

function search(query) {
  return Observable.create(observer => searchInto(observer, query, 0));
}

function searchInto(observer, query, start) {
  runQuery(query, start).subscribe(result => {
    observer.next(result);
    if (hasMorePages(result)) {
      searchInto(observer, query, start + 1);
    } else {
      observer.complete();
    }
  });
}

现在,搜索请求可能需要一段时间,如果用户更改了查询,我也不想检索所有页面。

让我们说搜索返回3页,用户在加载一页后更改查询。我希望看到类似的东西:

USER: types query A
CODE: loads page A1
USER: types query B
CODE: loads page B1
CODE: loads page B2
CODE: loads page B3

switchMap完成了一半的工作。得到的可观测量具有正确的序列:A1,B1,B2,B3。大。

然而,在幕后我的递归搜索仍在运行所有查询,给服务器,网络等带来不必要的负担。switchMap确实丢弃了#34;过时的"结果,但它不会阻止递归函数完成其工作。换句话说,它看起来像:

USER: types query A
CODE: loads page A1   -> returned by search observable
USER: types query B
CODE: loads page A2   -> discarded by search observable
CODE: loads page B1   -> returned by search observable
CODE: loads page B2   -> returned by search observable
CODE: loads page A3   -> discarded by search observable
CODE: loads page B3   -> returned by search observable

" A"的顺序和" B"是随机的(受竞争条件限制),但并不重要。

我做错了什么?对此有什么惯用解决方案?

2 个答案:

答案 0 :(得分:1)

flatMap非常友好地取消订阅Observable,当它启动新的"流"时。制作人可以使用observer.isUnsubscribed的订阅状态来停止其工作:

function searchInto(observer, query, start) {
  runQuery(query, start).subscribe(result => {
    observer.next(result);
    if (hasMorePages(result) && !observer.isUnsubscribed) {
      searchInto(observer, query, start + 1);
    } else {
      observer.complete();
    }
  });
}

答案 1 :(得分:1)

int motorPin = 3; int motorDir = 12; int motorBr = 9; void setup() //this is executed only once at init { //pinMode(motorPin, OUTPUT); pinMode(motorBr, OUTPUT); pinMode(motorDir, OUTPUT); } void loop() //This will be executed over and over { if (Serial.available() > 0) { // here '1' (the character) is important as 1 is the number // and '1' equals 0x31 (ASCII) if(Serial.read() == '1') { digitalWrite(motorBr, LOW); digitalWrite(motorDir, HIGH); digitalWrite(motorPin, HIGH); delay(500); digitalWrite(motorBr, HIGH); } else if(Serial.read() == '0') { digitalWrite(motorBr, LOW); digitalWrite(motorDir, LOW); digitalWrite(motorPin, HIGH); delay(500); digitalWrite(motorBr, HIGH); } } } 只有在您返回可取消的switchMap时才能取消操作。由于您未在Observable内退回Subscription,因此无法取消正在进行的操作。

因为在这种情况下使用Observable.create并没有真正帮助你,我建议您使用expand运算符来执行递归操作:

Observable.create