node.js - 将 NodeJS 异步代码转换为 Spring Project Reactor

标签 node.js spring spring-boot project-reactor

我有以下 NodeJS 代码:

// req and resp are http request, response objects
var uri = req.getURI()
var pageView = new PageView(uri)

var token = req.token
if (token) {
    UserRepository.findByToken(token, function(notFound, user){
        if(notFound) {  // means  user not found by specified token
            var newUser = new User('John Doe')
            user.foo = 'some value'
            processUser(newUser, pageView)

        } else {  // user found by token
            user.foo = 'some value'
            processUser(user, pageView)
        }
    })
} else {  // token does not exist
    token = new Token('some value')
    resp.setToken(token)
    var newUser = new User('John Doe')
    user.foo = 'some value'

    processUser(newUser, pageView)

}



 processUser(user, pageView) {

    PageViewRepositiry.save(pageView, function(error, savedPageView){
        if(error) {
            throw 'error'
        }
        user.pageViews.push(savedPageView) 
        // save the modified savedUser
        UserRepository.save(user , function(error, savedUser){

        })

     })

   }

它使用存储库模式作为数据库层的抽象(与 Spring 应用程序中的存储库模式相同)。 基本上它通过传入 token (来自 http req 对象)找到用户。如果找到用户,则更新用户实体并添加保存的 pageView 实体并保存修改后的用户。如果通过 token 未找到用户,则会创建一个新用户,使用保存的 pageView 更新用户,然后保存用户。

如何在 Spring Project Reactor (Flux) 中编写相同的代码?

不使用block()是否可以解决这个问题?理想情况下,我想要一个不使用 block() 的解决方案。

最佳答案

首先,如果 token 不存在,您有一些逻辑来生成 token 。例如:

private Mono<String> getToken(String token) {
     return Mono
         .just(token)
         .switchIfEmpty(Mono.just("some token"));
}

在这种情况下,使用 switchIfEmpty 有点大材小用了。为此,但我假设您生成 token 的过程有点复杂,否则您可以使用 Optional<String>相反(例如 token.orElse("some token") )。

此外,我们还有一些逻辑可以通过 token 查找用户,或者在给定 token 没有用户的情况下创建新用户:

private Mono<User> findUserByToken(String token) {
    return userRepository
        .findByToken(token)
        .switchIfEmpty(userRepository.save(new User("John Doe", token)));
}

现在我们有了这些方法,我们可以创建一个 PageView并一路使用这些方法。我从创建 PageView 开始的原因是因为这是整个 token 中的第一个“常量”,无论是否找到 token /用户:

return Mono
    .just(new PageView(uri))
    .flatMap(pageViewRepository::save)
    .flatMap(pageView -> getToken(token)
        .flatMap(this::findUserByToken)
        .doOnNext(user -> user.setFoo("foo"))
        .doOnNext(user -> user.getPageView().add(pageView)))
    .flatMap(userRepository::save)
    .map(User::getToken);

现在,由于您需要将 token 添加到响应中,并且我发现该 token 是 User 的一部分以某种方式对象(否则 UserRepository.findByToken() 将不起作用?),使用 User::getToken 会更容易最后检索要传递给响应的 token 。

<小时/>

请注意,存储库模式确实可以与 Spring 一起正常工作,但仅对 MongoDB、Cassandra、Couchbase 和 Redis 提供响应式(Reactive)支持。除此之外,还通过 rdbc 对 PostgreSQL 提供响应式(Reactive)支持,但我认为 Spring 数据不支持这一点。

关于node.js - 将 NodeJS 异步代码转换为 Spring Project Reactor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54205125/

相关文章:

javascript - nodejs : Error: EADDRNOTAVAIL, 无法分配请求的地址

java - 带唯一文件名的 Spring Boot YAML 配置

JSON 解析错误 : Can not construct instance of java. time.LocalDate: 没有从字符串值反序列化的字符串参数构造函数/工厂方法

java - Docker(Spring Boot 或 Thorntail)和 Keycloak

node.js - Socket.io 命名空间和服务器不共享中间件?

mysql - t2.micro EC2 实例运行太慢一段时间后恢复正常

node.js - 如何创建一个可以向其传递参数的nodejs模块?

java - Spring Integration - FTP 下载后立即发送消息

java - 如何编写具有可变数量的表单字段和文件的 Spring MVC Controller 方法?

java - Spring 全局异常处理程序 - 不是 MVC