debounceTime 仅在第一个值之后

debounceTime only after first value

有没有一种简单的方法可以使 debounceTime 在第一个值上立即生效?

searchQueries.pipe(debounceTime(1000))

假设我将搜索查询去抖动到 1 秒。

我的理解是这会导致第一次搜索延迟 1 秒,但是,我希望第一次搜索查询是即时的。

(例如,在此示例中 https://stackblitz.com/edit/typescript-adheqt?file=index.ts&devtoolsheight=50 如果我快速键入 123,它只会记录 123,但我希望它记录 1,然后记录 123)

我可以试试

merge(searchQueries.pipe(first()),searchQueries.pipe(debounceTime(1000)))

但这可能会延迟第二次搜索,但可能已经足够了。

有没有我缺少的配置 debounceTime 的方法?还是我应该使用油门或其他东西?

您可以使用 multicast 甚至 throttleTime:

searchQueries.pipe(
  multicast(new Subject(), s => merge(
    s.pipe(take(1)),
    s.pipe(skip(1), debounceTime(1000)),
  )),
);

从 RxJS 6 开始,throttleTime 运算符接受一个配置参数,您可以在其中告诉它发出前导和尾随发射。也许这会做你想做的而不是 debounceTime.

searchQueries.pipe(
  throttleTime(1000, undefined, { leading: true, trailing: true }),
);

这是我的 2 美分/我用 java-ngrx.

从另一个 post 修改的答案

dbounce-time-after.ts

import { OperatorFunction, SchedulerLike, concat } from "rxjs";
import { async } from "rxjs/internal/scheduler/async";
import { debounceTime, publish, take } from "rxjs/operators";

export function debounceTimeAfter(
  amount: number,
  dueTime: number,
  scheduler: SchedulerLike = async,
): OperatorFunction<number, number> {
  return publish(value =>
    concat(
      value.pipe(take(amount)),
      value.pipe(debounceTime(dueTime, scheduler))),
    )
  );
}

export function debounceTimeAfterFirst(
  dueTime: number,
  scheduler: SchedulerLike = async,
): OperatorFunction<number, number> {
  return debounceTimeAfter(1, dueTime, scheduler);
}

example.ts

of(1, 2, 3, 4, 5)
  .pipe(
    tap(value => console.log("TAP", value)),
    debounceTimeAfterFirst(50)
  )
  .subscribe(value => console.log(value));

控制台

TAP 1
1
TAP 2
TAP 3
TAP 4
TAP 5
5

但您也可以在 n 次发射 debounceTimeAfter 后开始去抖动。

使用debounce代替debounceTime更灵活。

searchQueries.pipe(debounceTime(1000))

等于:

searchQueries.pipe(debounce(() => timer(1000))

您可以创建自己的启发式来确定需要使用的超时时间。例如:

searchQueries.pipe(debounce(() => timer(getTimeout()))

...

const getTimeout = () => {
    return iterations === 1 ? 0 : 1000;
};

在那种情况下,您需要自己跟踪迭代计数并随着每个值增加它,但是有很多方法可以做到这一点而不会弄乱代码。我只是创建了一个包含原始可观察对象和计数逻辑的包装可观察对象。像这样:

export default class ObservableWrapper {

    ...

    next(parameters) {
        this.iterations++;
        this.observable.next(parameters);
    }
}