RxJs动态throttleTime duration a.k.a.获取滚动启动事件流 你好

RxJs动态throttleTime duration a.k.a.获取滚动启动事件流 你好,rxjs,Rxjs,首先,感谢您阅读本文 虽然这个解决方案看起来有点复杂,但它实现了您描述的行为,并且可以干净地封装在自定义操作符中 从'rxjs'导入{of,merge,NEVER}; 从“rxjs/operators”导入{share、exhaustMap、debounceTime、TakeTill}; const firstAfterInactiveFor=(ms)=>(源)=>{ //多播源,因为我们需要订阅它两次。 constSharedSource=source.pipe(share()); 返回sha

首先,感谢您阅读本文 虽然这个解决方案看起来有点复杂,但它实现了您描述的行为,并且可以干净地封装在自定义操作符中

从'rxjs'导入{of,merge,NEVER};
从“rxjs/operators”导入{share、exhaustMap、debounceTime、TakeTill};
const firstAfterInactiveFor=(ms)=>(源)=>{
//多播源,因为我们需要订阅它两次。
constSharedSource=source.pipe(share());
返回sharedSource.pipe(
//忽略源,直到我们完成从排气图返回的可观测数据
//回拨
排气图((第一个事件)=>
//创建一个只发出初始滚动事件,但从不发出的可观察事件
//完成(自己完成)
合并(属于(第一个事件),从不)。管道(
//一旦源处于休眠状态,完成永无止境的可观察项
//指定的持续时间。一旦发生这种情况,下一个源事件
//将被允许通过,并且该过程将重复。
takeUntil(sharedSource.pipe(debounceTime(ms)))
)
)
);
};
//这实现了期望的行为。
流管(第一个(500))

虽然此解决方案看起来有点复杂,但它实现了您描述的行为,并且可以干净地封装在自定义运算符中

从'rxjs'导入{of,merge,NEVER};
从“rxjs/operators”导入{share、exhaustMap、debounceTime、TakeTill};
const firstAfterInactiveFor=(ms)=>(源)=>{
//多播源,因为我们需要订阅它两次。
constSharedSource=source.pipe(share());
返回sharedSource.pipe(
//忽略源,直到我们完成从排气图返回的可观测数据
//回拨
排气图((第一个事件)=>
//创建一个只发出初始滚动事件,但从不发出的可观察事件
//完成(自己完成)
合并(属于(第一个事件),从不)。管道(
//一旦源处于休眠状态,完成永无止境的可观察项
//指定的持续时间。一旦发生这种情况,下一个源事件
//将被允许通过,并且该过程将重复。
takeUntil(sharedSource.pipe(debounceTime(ms)))
)
)
);
};
//这实现了期望的行为。
流管(第一个(500))

我制作了第三个版本,将我的解决方案封装到基于@backtick answer的自定义运算符中。这个解决方案有问题吗?内存泄漏还是什么?我不确定内部控制器Stream是否会正确销毁或完全销毁

const firstAfterInactiveFor=(ms)=>(source)=>{
const controllerStream=源管道(去BounceTime(ms));
返回源
.烟斗(
节流阀(()=>controllerStream{
领导:对,,
尾随:false
})
)
};
//这实现了期望的行为。
流动
.烟斗(
firstAfterInactiveFor(500)
)
.订阅(()=>{
console.log(“滚动启动”);
});
下面是代码笔,比较了这三种代码:

编辑: 使用日志和取消订阅按钮的更好示例

我制作了第三个版本,将我的解决方案封装到基于@backtick answer的自定义运算符中。这个解决方案有问题吗?内存泄漏还是什么?我不确定内部控制器Stream是否会正确销毁或完全销毁

const firstAfterInactiveFor=(ms)=>(source)=>{
const controllerStream=源管道(去BounceTime(ms));
返回源
.烟斗(
节流阀(()=>controllerStream{
领导:对,,
尾随:false
})
)
};
//这实现了期望的行为。
流动
.烟斗(
firstAfterInactiveFor(500)
)
.订阅(()=>{
console.log(“滚动启动”);
});
下面是代码笔,比较了这三种代码:

编辑: 使用日志和取消订阅按钮的更好示例

谢谢您的回答,与我的解决方案相比,它看起来真的很复杂。。现在,我想知道是否可以将我不太详细的解决方案封装到自定义运算符中:请查看我的第二个解决方案是否看到任何可能的问题,谢谢:)谢谢您的回答,与我的解决方案相比,它看起来真的很复杂。。现在,我想知道是否可以将我的不太详细的解决方案封装到自定义运算符中:请查看我的第二个解决方案,您是否看到任何可能的问题,谢谢:)我认为我们的解决方案的行为大致相同-我对
节流
没有太多实际操作经验,因此我误解了您的用法。我在这里看到的唯一问题是,您的操作员订阅了两次
source
——一次在
controllerStream
中,一次在返回值中。请参阅我关于多播的说明。从我对RxJs工作原理的理解来看,当我使用管道观察时,我没有订阅,因此我认为在返回值的末尾只有一个订阅。。您知道如何调试有多少活动订阅吗?我还没有找到容易的解决办法。。但也许我会尝试我在这里发现的那些更复杂的方法:取决于你想得到的复杂程度,但是有一种非常基本的方法来跟踪订阅-
Rx.defer
。看这个。要解决订阅的初始问题,是的,您需要拨打一个电话来订阅。但在引擎盖下有多个订阅启动。因为您引用了两次
源代码
,一次是去抖动,一次是节流,它将被订阅两次。@backtick谢谢您的要点,非常简单。是的,关于多个订阅,你是对的,我没有意识到第二个,但无论如何,我做了一些测试,它似乎可以订阅,也可以根据需要自动取消订阅。请参阅日志:那么我还需要使用share operator吗?我认为我们的解决方案的行为大致相同-我对
节流阀没有太多实际操作经验,因此我误解了您的用法。我在这里看到的唯一问题是