map vs flatMap in reactor
我已经找到了很多有关RxJava的答案,但是我想了解它在Reactor中的工作方式。
我目前的理解非常模糊,我倾向于认为map是同步的,而flatMap是异步的,但是我真的无法解决它。
这里是一个例子:
1 2 3 4 5 6 7 8 | files.flatMap { it -> Mono.just(Paths.get(UPLOAD_ROOT, it.filename()).toFile()) .map {destFile -> destFile.createNewFile() destFile } .flatMap(it::transferTo) }.then() |
我有文件(a
此示例摘自一本书。
我可以将所有
-
map 用于同步,非阻塞,一对一转换 -
flatMap 用于异步(非阻塞)的1到N转换
区别在方法签名中可见:
-
map 接受Function<T, U> 并返回Flux<U> -
flatMap 接受Function<T, Publisher<V>> 并返回Flux<V>
这是主要提示:您可以将
另一方面,
关于1-N方面:
对于每个
将
但这就是简朴的情况。一般情况是
例如,假设您有一个反应性数据库,并且您从一系列用户ID中获取了flatMap,并且请求返回了一个用户集
是:它在操作员应用它的方式(一个简单的方法调用,然后操作员发出结果)上是同步的,并且在函数本身不应该阻止操作员调用它的意义上说是非阻塞的。换句话说,它不应该引入延迟。这是因为
如果您的map函数正在阻止/引入了延迟,但无法转换为返回
flatMap方法与map方法类似,不同之处在于您提供的供应商应返回
使用map方法将导致
而使用flatMap会导致
例如,当您必须进行网络调用以检索数据时,使用返回一个Mono的java API,然后进行另一个需要第一个结果的网络调用的实用程序非常有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Signature of the HttpClient.get method Mono<JsonObject> get(String url); // The two urls to call String firstUserUrl ="my-api/first-user"; String userDetailsUrl ="my-api/users/details/"; // needs the id at the end // Example with map Mono<Mono<JsonObject>> result = HttpClient.get(firstUserUrl). map(user -> HttpClient.get(userDetailsUrl + user.getId())); // This results with a Mono<Mono<...>> because HttpClient.get(...) // returns a Mono // Same example with flatMap Mono<JsonObject> bestResult = HttpClient.get(firstUserUrl). flatMap(user -> HttpClient.get(userDetailsUrl + user.getId())); // Now the result has the type we expected |
此外,它还允许精确地处理错误:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public UserApi { private HttpClient httpClient; Mono<User> findUser(String username) { String queryUrl ="http://my-api-address/users/" + username; return Mono.fromCallable(() -> httpClient.get(queryUrl)). flatMap(response -> { if (response.statusCode == 404) return Mono.error(new NotFoundException("User" + username +" not found")); else if (response.statusCode == 500) return Mono.error(new InternalServerErrorException()); else if (response.statusCode != 200) return Mono.error(new Exception("Unknown error calling my-api")); return Mono.just(response.data); }); } } |