我收听ResizeObserver(或更确切地说,是一个polyfill)来触发对fabricjs画布的重绘,这是非常耗费资源的。因此,我想限制resize事件触发的重绘次数。
我尝试用RxJs实现此功能:
RxJs提供了一些built-in time-based operators。但是,它们都有缺点:
我尝试合并/加入这些运算符,但这导致n秒后出现双重呼叫和其他问题。有没有简单的RxJs方法可以做到这一点?我想可以通过启动/清除超时功能来实现。
答案 0 :(得分:1)
首先想到的是编写自己的管道运算符: https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#build-your-own-operators-easily
或者,您可以尝试如下操作:
3.6+
答案 1 :(得分:1)
您可以将throttleTime
与选项trailing
一起使用以发出最后一个事件。最后一个事件将以给定的延迟发出,并且当您停止调整大小时不会立即发出。
由于您还希望发出第一个事件,因此您还需要默认选项leading
。将两者都设置为true
将导致两个事件在每个新时间间隔的结尾和开头直接一个接一个地触发。为防止这种情况,您可以添加debounceTime
,且间隔要短一些,例如50ms。
import { fromEvent, asyncScheduler } from 'rxjs';
import { throttleTime, debounceTime, map } from 'rxjs/operators';
const source = fromEvent(window, 'resize').pipe(map(e => e.target['innerWidth']));
const width = source.pipe(
throttleTime(1000, asyncScheduler, { leading: true, trailing: true }),
debounceTime(50)
)
答案 2 :(得分:1)
您可以编写自己的函数,并在局部变量中跟踪最后发出和接收的项目。要在Rx中读取时间,您应该使用scheduler.now()
,这样可以使您的代码可测试。使用switchMap
,您可以使用switchMap(()=>of(e).pipe(delay(duration)))
来模拟油门行为。使用此功能,我们可以对最后一个项目很久以前要立即发出下一个项目的情况进行特殊处理。
这导致以下解决方案:
function limitTime(duration, scheduler = async) {
return (src) => new Observable(ob => {
var last = scheduler.now() - duration;
return src.pipe(
switchMap(e => {
var last2 = last;
last = scheduler.now();
if(last - last2 > duration) {
return of(e);
}
return of(e).pipe(delay(duration + last2 - last, scheduler),
tap(() => last = scheduler.now()));
})
).subscribe(ob);
})
}
通过一些测试here看到它的实际效果。