0

我有 Angular 输入,每次它的值发生变化时,我都会要求服务获取有关输入值的一些数据。我只关心上次输入的输入,所以当用户输入“1”,然后将其删除并输入“2”时,我不关心有关先前值的数据。我写了这样的东西(我在 prevNr 中保留了先前请求的值):

let stream,
  nr = document.querySelector('input').value;

if (status === `${nr} in progress`) {
  stream.unsubscribe();
  console.log(`subscription of ${prevNr} cancelled`)
}

status = 'in progress';
prevNr = nr;

console.log(`started subscription of ${nr}`)
stream = someService.someMethod.subscribe(() => {
  const clonedNr = nr;
  setTimeout(() => {
    status = 'done';
    console.log(`received response for ${clonedNr}`)
  }, 12000);
})

我在控制台中得到的是

1 in progress

subscription of 1 cancelled
2 in progress

subscription of 2 cancelled
3 in progress

subscription of 3 cancelled
4 in progress

received response for 1
received response for 2
received response for 3
received response for 4

现在我通过 setTimeout() 模拟响应,但我可以想象在输入 3 的数据之前接收输入 4 的数据的情况,因此该数据将被分配给错误的输入。如何在 Observable 中省略以前的请求?那可能吗?

4

1 回答 1

0

几点注意事项:

您可能想为流添加去抖动nr功能。这样,如果用户快速连续键入多个号码,您就不会为每个号码发送请求。debounceTime()让您在输入值后等待设定的毫秒数,如果在那段时间内没有输入新值,则将其传递。如果在设定的时间内输入了新值,时间将被重置;冲洗并重复。

您不应该在 中进行异步工作subscribe(),它“有点”会破坏 Rx。所有异步工作都应该subscribe()在另一个操作员内部完成;经常是*Map()操作员之一。


我假设someMethod()返回一个 observable(或者你可以将它转换为一个),在这种情况下你会想要switchMap()操作符。你在里面返回一个 observable switchMap(),它只会订阅最近的 observable。它还将取消订阅之前的 observable。

let stream,
nr = document.querySelector('input').value
    .debounceTime(500); // This will wait 500 ms before passing on a value
                        // If a new value arrives before 500ms has passed, it resets the time

stream = nr
    .switchMap(num => someService.someMethod(num))
    .subscribe(clonedNr => console.log(`received response for ${clonedNr}`));
于 2017-07-19T09:56:07.513 回答