- 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/
我刚刚开始使用 javascript,多年来一直使用 C# 和 OO 语言。 我发现我将我的代码放在这样的文件中, database.js sync.js date.js 而且感觉非常程序化,基本上就
当我运行 git clean --dry-run 时,结果有点像: Would remove an_untracked_file Would remove an_untracked_file_2 Wo
嘿,第一次在 Stack Overflow 上提问,所以请放轻松! 我最近开始开发一个 CMS 驱动的网站,该网站需要多语言功能(12 种语言!)。我过去曾推出过 Expression Engine/
我正在使用可移植类库构建 Android/iOS xamarin 表单应用程序。我正在寻找在 PCL 项目中执行此示例的最佳方法: https://msdn.microsoft.com/en-us/l
我经常听到有关"new"MV* 框架的信息。我修改了 KnockoutJS,创建了一个发票应用程序,但我更喜欢用原始 JavaScript 编写干净、模块化的代码——必要时利用实用程序 API 和其他
我有这段 javascript 代码,当我点击按钮时, Canvas 会被清除。 但是当我移动鼠标时, Canvas 会显示我之前写的内容,而且它不会以空白 Canvas 开始 单击按钮后如何从空白
我有一个带有 5 个内部字符串变量的对象,但其中 3 个是可选的。我可以为每个可能的组合创建一个构造函数,或者我可以调用通用构造函数并向其传递一些空字符串。后一种情况对我来说很有趣,如果我在调用构造函
我是 SQL 的新手。我正在尝试从数据库 (Postgres) 获取数据,如果这些数据无效,则即时替换它们。是否可以使用纯 SQL 来执行此操作?例如,在我的数据库 users 中,我有包含以下数据的
当我清理 TOMCAT 或清理 tomcat 工作目录时,我丢失了保存在 Tomcat 文件夹中的所有文件,我可以禁用此选项吗? 最佳答案 清理 tomcat 工作目录将清除部署到 Tomcat 中的
我正在清理我的一个旧项目。它必须做的一件事是——给定笛卡尔网格系统和网格上的两个正方形,找到所有正方形的列表,连接这两个正方形中心的线将通过这些正方形。 这里的特殊情况是所有起点和终点都被限制在正方形
我现在正在学习如何使用 makefile 并制作了以下 makefile(我在 Windows 上使用 visual studio 命令行编译器) CC = cl CFLAG = /EHsc test
我做了 git checkout master。如果我执行 git status 它会在我的工作目录中显示两个更改的文件,即使我没有碰过它们。这似乎是某种行尾问题。 git reset --hard
在我看来,Makefile 规则大致可以分为“积极”和“消极”规则:“积极”规则创建丢失或更新过时的文件,而“消极”规则删除文件。 为“肯定”规则编写先决条件非常简单:如果目标和先决条件是文件名,ma
我的电脑上安装了 WAMP,我想在其中运行 Drupal 6。 当我安装 Drupal 时,我可以选择激活 Clean URL。 首先,我将 Drupal 安装放在 www 文件夹中,我可以选择启用干
考虑以下堆栈跟踪: In [3]: f.clean() ------------------------------------------------------------------------
我放弃了。我已经阅读了这里的几十个问题,甚至问了我自己的问题,我尝试了很多事情,我只是不知道该怎么做。 我需要使用以下格式创建 url:(NSFW 链接,请注意) http://jbthehot.co
下面的代码是我目前的解决方案。 我试图模仿的一个很好的例子是 FrameworkElement.ActualWidth 属性。您知道 ActualWidth 属性是如何计算和重新分配的,每当 Widt
当然,Ruby 确实有递归,就像任何其他高级编程语言一样。只要递归深度不是太高,这就可以正常工作,但如果是,您将捕获堆栈溢出: #!/usr/bin/ruby2.0 def rec_naive(i)
我找到的最短方法是: n = 5 # Python 2. s = str(n) i = int(s) # Python 3. s = bytes(str(n), "ascii") i = int(s)
这是一种经常出现的情况,对我来说永远不会太容易。我想我会问其他人如何处理它。 想象一下,如果 demo=60 命令行参数的处理是这样完成的: if DemoOptionSpecified() {
我是一名优秀的程序员,十分优秀!