- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试通过重构一些当前阻塞的代码来学习响应式(Reactive)编程。我多次遇到在 Mono 序列中设置某些可变数据对象的状态而不订阅它的问题。在旧代码中,对象的字段值是由某些阻塞服务计算的,我现在也在 Mono
中执行此操作。
到目前为止,我通常(ab)使用 flatMap
来获得预期的行为:
initExpensiveObject().flatMap(expObj -> initExpensiveField(expObj).map(expField -> {
expObj.setExpensiveField(expField);
return expObj;
})).subscribe(expObj -> System.out.println("expensiveField: " + expObj.getExpensiveField()));
import reactor.core.publisher.Mono;
public class Main {
/**
* Expensive, lazy object instantiation
*/
public static Mono<ExpensiveObject> initExpensiveObject() {
return Mono.fromCallable(ExpensiveObject::new);
}
/**
* Expensive, async mapping (i.e. database access, network request):
* ExpensiveObject -> int
*/
public static Mono<Integer> initExpensiveField(ExpensiveObject expObj) {
return Mono.just(1);
}
public static class ExpensiveObject {
private int expensiveField = -1;
public int getExpensiveField() {
return expensiveField;
}
public void setExpensiveField(int expensiveField) {
this.expensiveField = expensiveField;
}
}
}
虽然这个 flatMap
模式有效,但我觉得应该有一个更具 react 性的解决方案。考虑到Mono
中有如此多的运算符单独而言,从一个对象“映射”到同一对象以改变其状态的直觉感觉是错误的。然而,“副作用”运算符 (doOn*
) 不允许在不订阅另一个发布者的情况下轻松转换它。
如果我的问题没有简单的解决方案,我非常愿意接受设计改进,因为代码的设计仍然是顺序。
最佳答案
While this flatMap-pattern works, I feel like there should be a more reactive solution.
这可能不是您想要听到的答案,但 react 性解决方案是完全放弃可变性。在更复杂的示例中,在 react 链中传递可变对象可能会导致无意的副作用,这可能会导致一些相当难以追踪的错误。完全重构可变性要容易得多。
I'm very much open to design improvements if there is no trivial solution to my problem
我会采取的“最少改变”方法是:
ExpensiveObject
不可变的。删除 setter 方法,并提供另一个采用 expensiveField
显式值的构造函数。 .withExpensiveField()
(或 ofExpensiveField()
,或其他完全不同的东西,请选择!) ExpensiveObject
上的方法这需要 Mono<Integer>
对于 expensiveField
并返回 Mono<ExpensiveObject>
.flatMap()
构建 react 链调用,并且看不到可变对象: initExpensiveObject()
.flatMap(expObj -> expObj.withExpensiveField(initExpensiveField(expObj)))
.subscribe(expObj -> System.out.println("expensiveField: " + expObj.getExpensiveField()));
以上代码经过修改:
public class Main {
/**
* Expensive, lazy object instantiation
*/
public static Mono<ExpensiveObject> initExpensiveObject() {
return Mono.fromCallable(ExpensiveObject::new);
}
/**
* Expensive, async mapping (i.e. database access, network request):
* ExpensiveObject -> int
*/
public static Mono<Integer> initExpensiveField(ExpensiveObject expObj) {
return Mono.just(1);
}
public static final class ExpensiveObject {
private final int expensiveField;
public ExpensiveObject() {
expensiveField = -1;
}
private ExpensiveObject(int expensiveField) {
this.expensiveField = expensiveField;
}
public int getExpensiveField() {
return expensiveField;
}
public Mono<ExpensiveObject> withExpensiveField(Mono<Integer> expensiveField) {
return expensiveField.map(ExpensiveObject::new);
}
}
}
您可能希望根据最终设计更改上述内容(例如 with
方法对单个字段对象没有多大意义),但这概括了主要思想。
关于java - react 堆项目 : Reactively transform mutable object's state with another Publisher in same sequence,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58606433/
根据下面的链接,我应该能够配置Web一键发布。甚至还有屏幕截图显示如何实现这一目标。但是,我在解决方案资源管理器中找不到该选项。我是弱智还是瞎子?! 如果有人质疑我的理智和在菜单上查找项目的能力,我很
我使用 OAuth 框架,它像这样异步创建经过身份验证的请求: OAuthSession.current.makeAuthenticatedRequest(request: myURLRequest)
我如何跨此 我为一个简单的秒表编写了代码,它也可以兼用作Rubik的立方计时器。源代码和可执行文件在这里: Cube timer 无论如何,我的疑问不是关于此代码的(它工作正常)。 我下载了我上传的可
我想使用 Apple 的新 Combine 框架从列表中的每个元素发出多个请求。然后我想要一个减少所有响应的单一结果。基本上,我想从发布者列表转到拥有响应列表的单个发布者。 我尝试制作一个发布商列表,
我在 EnvironmentObject 中为我的应用创建了一个“状态”对象像这样: class AppState: ObservableObject { @Published var cou
将企业应用程序部署到服务器(例如 Glassfish 或 JBoss)时,完全发布和增量发布有什么区别? 我看到部署的工件树中列出了几个模块,但是当我在 Web 存档上使用增量发布时,会发生一些事情,
我找不到这个记录。假设我想将一个端口发布到一个已知的地方,但有时会发布所有其他“暴露”的端口以进行调试或测试。 一个简单的 Dockerfile FROM alpine CMD /bin/sleep
在使用 ivy:publish ant 任务发布工件时,工件名称会附加我们为 ivy:publishrevision/pubrevision 属性指定的任何内容> 任务。 有没有办法将时间戳附加到这个
来自数据库系统概念,用于对象关系数据库的 SQL 命令: create type Publisher as (name varchar(20), branch varchar(20)); create
我有一个发布功能如下: Meteor.publish('tasks', function (name) { var project = Projects.findOne({name: name
我目前正在尝试实现两个出版商的合并。但是我找不到适合我的用例的解决方案。 我想合并 2 个发布者,它们都发出相同类型的结构数组。我希望合并的发布者在任一合并的发布者发出新值时发出值。 基本上这将是 P
我正在尝试复制 WWDC 2019 session “结合实践”中给出的“Wizard School Signup”示例 https://developer.apple.com/videos/play
我遇到 TweetInvi 0.9.9.7 无法上传视频的问题。该视频是一个 9MB 的 MP4 视频,我可以使用网络界面将它上传到 Twitter。我收到的错误消息是: The tweet cann
我在本地使用第三方库,我使用他们提供的步骤安装了所有内容。 我对包运行了 composer require 并运行了更新。这安装到 vendor 文件夹中。 然后我将路径添加到 config/app
尝试编译以下代码时: class LoginViewModel: ObservableObject, Identifiable { @Published var mailAdress: Str
我使用 .NET Core Framework 在 Visual Studio 2015 中创建了一个简单的 Web API 项目。当我使用默认设置发布此项目时,它会创建以下内容: 总共有 155 个
我正在 Laravel 7 中实现一个包并使用 https://github.com/jeroennoten/Laravel-AdminLTE作为引用。 在我的包内,我有以下结构 packages/m
当我尝试使用 Google 的结构化数据测试工具验证我的结构化数据时,出现错误: The attribute publisher.itemtype has an invalid value. 我在这条
刚从使用 Books 应用程序示例的 Djangobook 教程中学习时,您通过多对多关系将 Book 与 Author 相关,并将 Book 与 Publisher 相关。您可以使用 p.book_
我只是不得不这样做。绝对每个问题我都查找了有关此问题的问题,但他们的答案都没有帮助我解决问题。 我正在尝试在我的 Facebook 页面上发帖。 问题是: 错误:“(#100)您不能在已发布的帖子上指
我是一名优秀的程序员,十分优秀!