gpt4 book ai didi

java - react 堆项目 : Reactively transform mutable object's state with another Publisher in same sequence

转载 作者:行者123 更新时间:2023-11-30 05:25:57 26 4
gpt4 key购买 nike

我正在尝试通过重构一些当前阻塞的代码来学习响应式(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 显式值的构造函数。 .
  • 提供“响应式(Reactive)”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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com