与 Mono.just 和 then(Mono.just) 的混淆

问题描述 投票:0回答:1

我正在学习反应式 Java,我正在尝试从数据库中执行删除操作。我使用的数据库是嵌入式 Mongo DB。

我尝试了很少的方法来从数据库中删除具有给定 ID 的电影,其中一些有效,其余的无效。想知道我是否缺少反应式编程的一些基本概念。

示例 1:删除工程

 return moviesInfoService.deleteMovieInfoById(id)
                .then(Mono.just(ResponseEntity.noContent().build()));

例子2:删除不起作用

moviesInfoService.deleteMovieInfoById(id);
return Mono.just(ResponseEntity.noContent().build());

示例3:删除不起作用

Mono<Void> result = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> result2 = result.map(m -> ResponseEntity.noContent().build());
return result2

示例 4:删除工作

return moviesInfoService 
                .getMovieInfoById(id)
                .flatMap(fm -> moviesInfoService.deleteMovieInfoById(fm.getMovieInfoId()))
                .then(Mono.just(ResponseEntity.noContent().build()));

我无法理解为什么在某些情况下删除有效而在某些情况下无效。请帮助我。

java spring-boot mono spring-webflux
1个回答
0
投票

为什么它不起作用是因为你打破了链条,而且你还没有读过操作员的实际操作。

 return moviesInfoService.deleteMovieInfoById(id)
                .then(Mono.just(ResponseEntity.noContent().build()));

此处

deleteMovieInfoById
返回一个值,然后您调用
then
运算符,它将(当较早的函数完成时)丢弃该值,而是返回
ResponseEntity.noContent().build()
.

您可以只写

.then(ServerResponse.noContent().build())
,因为
ServerResponse
会给您一个
Mono
,或者如果您坚持要返回一个
ResponseEntity
,您可以改用
thenReturn(ResponseEntity.noContent().build())
,它将为您包裹在一个
Mono
中自动。

ResponseEntity
来自
http
包,这意味着它更通用,而
ServerResponse
来自
reactive
包,所以它更方便。

第二个不起作用,因为如果我们重写它更爆炸我们得到:

Mono<Void> someThing = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> response = Mono.just(ResponseEntity.noContent().build());
return response;

正如您在这里看到的,您有两个

Mono's
而其中一个(最上面的一个)未使用。在 reactor 入门中解释说 reactor 就像传送带一样工作。有两个阶段,
assembly
阶段和
subscription
阶段。你可以阅读它在这里.

这实际上意味着你不能让任何 mono/flux 悬空,你总是需要链接到最后一个运算符,以便反应式 java 可以对先前的函数结果做出反应。

你所谓的打破了链条.

你需要链接到

someThing
。在这里,我用
then
来做。

Mono<Void> someThing = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> response = someThing.then(ServerResponse.noContent().build());
return response;

你的例子 3 有点难以发现,这是因为你隐含地理解你不能映射

Void
.

Mono<Void> result = moviesInfoService.deleteMovieInfoById(id);
Mono<ResponseEntity> result2 = result.map(m -> ResponseEntity.noContent().build());
return result2

在您的示例中,

m
是什么?返回
Mono<Void
之前的功能所以
m
会是什么?如果你之前的函数没有返回任何东西,那就是这样,它不会在之后运行
map
函数。

所以基本上

map
不是在这里使用的运算符
then
或者
thenReturn
是应该使用的。

最后一个例子有效,是最惯用的解决方案。

return moviesInfoService 
                .getMovieInfoById(id)
                .flatMap(fm -> moviesInfoService.deleteMovieInfoById(fm.getMovieInfoId()))
                .then(Mono.just(ResponseEntity.noContent().build()));

然后我们可以将其重写为更详细的内容:

void Mono<ServerResponse> deleteMovie() {
    final MovieService movieService = new MovieService();
    return movieService.get("Terminator").flatMap(name -> {
        System.out.println("calling delete on: " + name);
        return movieService.delete(name);
    })
    .then(ServerResponse.noContent().build())
}

static class MovieService {

    public Mono<String> get(String s) {
        System.out.println("fetching " + s);
        return Mono.just(s);
    }

    public Mono<Void> delete(String s) {
        System.out.println("deleting " + s);
        return Mono.empty();
    }
}

如果你这样看

  • 你在取东西
  • 然后调用
    flatMap
    获取什么,这是允许的,因为我们有一些我们可以
    flatMap
    on.
  • 然后我们在
    delete
    中调用
    flatMap
    并且因为我们正在返回一个
    Mono<Void>
    它基本上只是告诉反应链我们已经完成并且没有返回任何内容
  • 然后我们只会对最后一步的完成做出反应并调用
    then
    ,我们返回
    ServerResponse

总是必须坚持你做的最后一件事。

其中大部分内容在反应式文档的反应式编程入门部分中进行了解释,并且您正在投票,因为它在 Stack Overflow 上已经回答了很多次。

© www.soinside.com 2019 - 2024. All rights reserved.