- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我将状态保存在一个 ReplaySubject
中,它会重播状态的最后一个副本。从该状态,派生出其他 ReplaySubjects
来保持……好吧,派生状态。每个重放主题只需要保存它的最后计算状态/派生状态。 (我们不使用 BehaviorSubjects
因为它们总是给出一个值,但我们只想要一个从我们的父 observables 派生的值。)总是需要重放如果我们已经生成派生状态,则对新订阅者的值(value)。
我有一个自定义的 observable 运算符,可以按照我想要的方式完成此操作,但感觉并不那么干净。我觉得应该有一种有效的方法可以让 RxJ 的运算符(operator)自己完成这个任务。
我已经尝试了两种最明显的方法,但每种方法都存在一些小问题。问题涉及取消订阅和重新订阅。打开下面的 fiddle ,打开控制台,然后单击运行。我将描述每个输出的问题。
https://jsfiddle.net/gfe1nryp/1/
refCount
ed ReplaySubject 的问题
=== RefCounted Observable ===
Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Resubscribe
Subscription 2: 3
Work
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
这很好用,中间函数在没有订阅时不做任何工作。但是,一旦我们重新订阅。我们可以看到订阅2重放了取消订阅前的最后一个状态,然后在base$
状态中根据当前值播放派生状态。这并不理想。
connect
ed ReplaySubject 的问题
=== Hot Observable ===
Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Work
Work
Work
Resubscribe
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
这与 refCount
ed observable 没有相同的问题,没有不必要的重播取消订阅前的最后一个状态。然而,由于 observable 现在很热,权衡是每当新值进入 base$
状态时我们总是工作,即使该值没有被任何订阅使用。
最后,我们有自定义运算符:
=== Custom Observable ===
Work
Subscription 1: 1
Work
Subscription 1: 2
Work
Subscription 1: 3
Unsubscribe
Resubscribe
Work
Subscription 2: 6
Work
Subscription 2: 7
Work
Subscription 2: 8
啊,两全其美。它不仅不会不必要地重播取消订阅前的最后一个值,而且在没有订阅时也不会做任何不必要的工作。这是通过手动创建 RefCount
和 ReplaySubject
的组合来实现的。我们跟踪每个订阅者,当它达到 0 时,我们刷新重播值。它的代码在这里(当然在 fiddle 中):
Rx.Observable.prototype.selectiveReplay = function() {
let subscribers = [];
let innerSubscription;
let storage = null;
return Rx.Observable.create(observer => {
if (subscribers.length > 0) {
observer.next(storage);
}
subscribers.push(observer);
if (!innerSubscription) {
innerSubscription = this.subscribe(val => {
storage = val;
subscribers.forEach(subscriber => subscriber.next(val))
});
}
return () => {
subscribers = subscribers.filter(subscriber => subscriber !== observer);
if (subscribers.length === 0) {
storage = null;
innerSubscription.unsubscribe();
innerSubscription = null;
}
};
});
};
所以,这个自定义的可观察对象已经可以工作了。但是,这可以只用 RxJS 运算符来完成吗?请记住,可能会有不止几个这样的主题链接在一起。在示例中,我只使用一个链接到 base$
来说明我在最基本级别尝试过的两种普通方法的问题。基本上,如果您只能使用 RxJS 运算符,并使输出与上面 === Custom Observable ===
的输出相匹配。这就是我要找的。谢谢!
最佳答案
您应该能够将 multicast
与主题工厂而不是主题一起使用。比照。 https://jsfiddle.net/pto7ngov/1/
(function(){
console.log('=== RefCounted Observable ===');
var base$ = new Rx.ReplaySubject(1);
var listen$ = base$.map(work).multicast(()=> new Rx.ReplaySubject(1)).refCount();
var subscription1 = listen$.subscribe(x => console.log('Subscription 1: ' + x));
base$.next(1);
base$.next(2);
base$.next(3);
console.log('Unsubscribe');
subscription1.unsubscribe();
base$.next(4);
base$.next(5);
base$.next(6);
console.log('Resubscribe');
var subscription2 = listen$.subscribe(x => console.log('Subscription 2: ' + x));
base$.next(7);
base$.next(8);
})();
multicast
operator 的重载完全满足您的用例。每次 multicast
运算符返回的可观察对象完成并重新连接时,它都会使用提供的工厂创建一个新主题。虽然它没有很好的文档记录,但它基本上从 Rxjs v4 复制了一个现有的 API。
如果我误解了或者不起作用,请告诉我,
关于javascript - 如何干净地重新连接到 ReplaySubject,同时避免过去的内存副作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42868235/
我有一些文档,它的创建时间以毫秒为单位。我需要将它们分为今天、昨天、过去 7 天、过去 30 天、超过 30 天。 我使用了以下代码:convertSimpleDayFormat(1347022979
我正在尝试创建一个 Crystal 报告,用于在图表中显示十二个月的月费率。 对于此任务,我有一个 dc_date(mm/dd/yyyy) 作为变量,我将其更改为 mmyyyy 格式。但是当我看到月份
我想使用 Linux 命令将年转换为天(过去)。例如: 用户给出的号码:10年前 程序应计算 10 年前的天数总和(例如:10*12*31(年/月/日)--> 3720 天)。 程序将其与今年开始的当
我的要求有点复杂,为了便于理解,让我用简单的例子说明一下。假设,我们必须计算过去 12 个月消费者按月购买的产品数量。所以我们要做的是: SELECT DATENAME(MONTH, m.Invoic
如果我今天(2012 年 8 月 21 日)运行查询,我想得到这个结果集: [...] 为了得到这个,我正在使用以下内容,但它似乎过于复杂。这可以简化吗? ;WITH Numbers_cte([num
这是我目前用来显示下周五日期的方法。 $date_friday = date('F j', strtotime('Friday')); print $date_friday; 我应该使用什么来显示过去
我有一个包含一个日期时间列的表。我只需要返回过去 6 个月的行。这可以通过 来完成 where datetime_column > DATEADD(m, -6, current_timestamp)
我正在为我的应用使用 Firestore,并且希望能够获得过去 7 天内发布的最受欢迎的项目。在理想的情况下,调用看起来像这样: let calendar = Calendar.cur
我有以下方法来计算时间: public static String sumTime(String date1, String date2) throws ParseException { Ca
我想检索过去 24 小时内发布的观看次数最多的前 10 个主题。如果网站在过去 24 小时内获得的主题少于 10 个,则必须检索前一天剩余的浏览次数最多的主题。 我以unix格式将时间存储在数据库中,
我想从我的 MySQL 服务器获取过去 x 个月的所有记录。例如使用 2 个月(不是过去 2 个月,比如过去 60 天,而是过去整个月等等。如果实际月份是 4 月,我想要 2 月和 3 月的所有记录)
我正在尝试使用 php 创建一个博客系统,我需要一种方法来计算过去 21 天内浏览次数最多的帖子。有人知道这样做的好方法吗? 我对 php 没有太多经验,所以我需要有人给我指出正确的方向。我试图研究
我正在尝试查找过去 26 周每周结束时的用户总数。 例如, 从第 26 周开始,该周有 100 名用户注册,并且有 20 名新用户注册,因此到第 26 周结束时,注册用户数量为 120 名 从第 25
假设我们有下表,列如下所示: Rides ride_id start_time end_time passenger_id driver_id ride
好的,我正在尝试获取过去 24 小时内包含“价格”列的所有行的平均值。 $tickerBuy = $this->model->ticker("date AS datetime, avg(price)
我有一个账户表,其中名为“dateCreation”的列是账户的创建日期。 我想获取过去 12 个月内创建的所有帐户,但有时 2 个月或更长时间都没有创建帐户。在这几个月里,我希望 mysql 返回
是否有办法检索过去 7 天内添加的所有用户?添加用户时,包含时间戳。日期被添加到他们的“信息”中。 例如这样: 因此日期公式为:D/M/YYYY。谁能帮我理解如何做到这一点? PS:奇怪的OL3gee
我有一个 Angualr 服务,可以列出从当前月份开始的 12 个月和年份: JS: app.factory('12months', function() { return {
我有一个弹出窗口,其中一个名为 fade 的元素应该扩展到屏幕的整个宽度(当没有可滚动内容时它会这样做)。但是,当内容超过浏览器窗口的 100% 时,它不会扩展到页面高度的 100%。 如果我设置 h
我正在尝试选择过去 5 天的整数字段的总和,我需要将它分组为每一天。 我在确定分组时遇到了一些问题。到目前为止,这是我的 sql 查询: select sum(`amount_sale`) a
我是一名优秀的程序员,十分优秀!