如何从返回Mono的流中创建Flux?

huangapple go评论71阅读模式
英文:

How to create Flux from a Stream that returns Mono?

问题

假设我有一个课程名称对象列表,其中包含(CourseID,Name)。让我们将该列表称为'courseNameList'。

当有人发送请求到"IP:port/courses"时,我们希望显示课程列表。

然而,在发送结果之前,我还需要附加每门课程的价格。价格将从另一个微服务中检索,并返回一个Mono对象。

因此,用户将看到包含(ID,Name,Price)的课程列表。价格来自另一个服务。

控制器方法可能如下所示:

@GetMapping("/courses")
public Flux<Course> getProducts() {
    return courseNameList.stream().map(courseName -> {
        // 进行WebClient调用以发送courseName.getID作为参数到定价服务,并获取'price' Mono对象
        // 返回包含id、name、price的课程对象
    })
    .collect(Collectors.toList())
    .flatMapMany(Flux::fromIterable);
}

我尝试了多种方式来返回Flux。但是,我无法弄清楚如何做到这一点。我需要将这些注释替换为等效的(或更好的)代码。

英文:

Imagine I have a list of coursename objects with (CourseID, Name). Let's call that list as 'courseNameList'.

When someone send's request to "<IP:port>/courses" we want to display list of courses.

However, before sending the results, I also need to append price of each course. The price will be retrieved from another Microservice and it returns a Mono object.

So, user will see list of courses with (ID, Name, Price). Where price comes from another service.

The controller method might look like this

@GetMapping(&quot;/courses&quot;)
public Flux&lt;Course&gt; gerProducts() {
 courseNameList.stream.map(courseName -&gt; {
      //Make a webClient call to pricing service by sending coureName.getID as parameter and get the &#39;price&#39; Mono object
      //return the course object with id, name, price
   })
     //Collect and return Flux with contains list of courses!
}

I tried multiple ways to return the Flux<Course>. But, I am unable to figure out how. I need those comments to be replaced with equivalent (Or better) code.

答案1

得分: 2

以流(Flux)而不是列表(list)开始会更好,但如果不可能的话,可以按照下面的方式从流创建Flux,然后使用flatMap而不是map。

@GetMapping("/courses")
public Flux<Course> getProducts() {
  return Flux.fromStream(courseNameList.stream()).flatMap(courseName -> {
    // 进行返回Mono的WebClient调用
  });
}
英文:

Starting with a flux rather than a list would be better, but if not possible then create the flux from a stream as below and then use flatMap instead of map.

@GetMapping(&quot;/courses&quot;)
public Flux&lt;Course&gt; gerProducts() {
  return Flux.fromStream(courseNameList.stream()).flatMap(courseName -&gt; {
    // Make webClient call which returns mono
  });
}

答案2

得分: 1

以下是已翻译的内容:

// I assumed you have courses list already as you are using a list.
// 我假设你已经有了课程列表,因为你正在使用一个列表。
List<String> list = List.of("a", "bb", "ccccc", "ddd");
Flux.fromIterable(list)
      // this is where you find the price and append
      .flatMap(a -> Mono.just(a).map(k -> k + ":" + k.length()))
      .subscribe(System.out::println);

//output
//输出
a:1
bb:2
ccccc:5
ddd:3

But if you have 100 courses, will you want to make 100 calls to the service one by one. Will it not affect the performance? Instead can you send the list of courses and get the price from the service in 1 call?

// you have courses list
// 你有课程列表
List<String> list = List.of("a", "bb", "ccccc", "ddd");

// get the price of all courses in 1 call
// 以1次调用获取所有课程的价格
Mono.fromSupplier(() -> List.of(1, 2, 5, 3))
        .flatMapIterable(Function.identity())
        .index()
        // map the courses and price
        // 映射课程和价格
        // I used index. but you could use courseID to map the price
        // 我使用了索引,但你可以使用课程ID来映射价格
        .map(t -> list.get(t.getT1().intValue()) + ":" + t.getT2())
        .subscribe(System.out::println);

请注意,代码部分未翻译,只翻译了注释和输出。

英文:

You can take a look at this example and come up with a solution yourself.

// I assumed you have courses list already as you are using a list.
 List&lt;String&gt; list = List.of(&quot;a&quot;, &quot;bb&quot;, &quot;ccccc&quot;, &quot;ddd&quot;);
 Flux.fromIterable(list)
       // this is where you find the price and append
       .flatMap(a -&gt; Mono.just(a).map(k -&gt; k + &quot;:&quot; + k.length()))                 
       .subscribe(System.out::println);

//output
a:1
bb:2
ccccc:5
ddd:3

But if you have 100 courses, will you want to make 100 calls to the service one by one. Will it not affect the performance? Instead can you send the list of courses and get the price from the service in 1 call?

// you have courses list
List&lt;String&gt; list = List.of(&quot;a&quot;, &quot;bb&quot;, &quot;ccccc&quot;, &quot;ddd&quot;);

// get the price of all courses in 1 call
Mono.fromSupplier(() -&gt; List.of(1, 2, 5, 3))
        .flatMapIterable(Function.identity())
        .index()
        // map the courses and price
        // I used index. but you could use courseID to map the price
        .map(t -&gt; list.get(t.getT1().intValue()) + &quot;:&quot; + t.getT2())
        .subscribe(System.out::println);

huangapple
  • 本文由 发表于 2020年7月29日 23:13:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63156797.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定