0

我正在尝试进行两个 API 调用,第二个 API 调用取决于第一个 API 响应。下面的代码给出了第一个 weblient 调用的响应。这里我没有得到第二个 API 调用的响应。在日志中,我可以看到对第二个 Web 客户端调用的请求甚至不是从 onSubscribe() 开始的。你能告诉我我做错了什么吗?

@Autowired
Issue issue;

List issueList = new ArrayList<>();

public Mono<Response> getResponse(Request request) {
   return webClient.post()
     .uri("myURI")
     .body(Mono.just(request),Request.class)
     .retrieve()
     .bodyToMono(Response.class)
     .flatMap(resp->{
           resp.getIssues().stream()
              .forEach(issueTemp -> {
                 issue = issueTemp;
                 webClient.get()
                    .uri("mySecondURI" + issueTemp.getId())
                    .retrieve()
                    .bodyToMono(Issue.class)
                     .flatMap(issueTemp2-> {
                        issue.setSummary(issueTemp2.getSummary());
                        return Mono.just(issue);
                     }).log();
           issueList.add(issue);
        });

        Response responseFinal = new Response();
        responseFinal.setIssues(issueList);
        return Mono.just(responseFinal);
    }).log();
}

更新 2:

我已将代码更改为 Functions 并使用 Flux 而不是流迭代。我现在面临的是,所有迭代都在 doSecondCall 方法中被过滤掉。请参考我在 doSecondCall 方法中的评论。因此不会触发第二次呼叫。如果我不应用过滤器,则会触发诸如“issue/null”之类的请求,这也会导致我的服务中断。

 public Mono<Response> getResponse(Request request) {
   return webClient.post()
     .uri("myURI")
     .body(Mono.just(request),Request.class)
     .retrieve()
     .bodyToMono(Response.class)
     .flatMap(r->
         doSecondCall(r).flatMap(issueList->{
             r.setIssues(issueList);
             return Mono.just(r);
           })
     );
}

public Mono<Issue> doSecondCall(Response r) {
          return Flux.fromIterable(r.getIssues())
                      .filter(rf->rf.getId()!=null) //everything gets filtered out
                      .flatMap(issue->getSummary(issue.getId()))
                      .collectList();
  }


public Mono<Issue> getSummary(Response r) {
          return webClient.get()
                       .uri("issue/"+id)
                       .retrieve()
                       .bodyToMono(Issue.class).log();

   }

[使用 WebFlux 的反应式编程如何处理依赖的外部 api 调用] @Thomas- 另外,刚刚找到了这个线程。他基本上说除非你阻止第一个电话,否则没有办法声明第二个电话。是这样吗?

4

1 回答 1

3

为什么您不触发第二次呼叫是因为您正在打破链条,正如我在这个答案中提到的(带有示例)。

停止破坏链条

// here...
.forEach(issueTemp -> {
    issue = issueTemp; // and this is just silly? why?
    webClient.get() // Here you are calling the webClient but ignoring the return value, so you are breaking the chain.
        .uri("mySecondURI" + issueTemp.getId())
        .retrieve()
        .bodyToMono(Issue.class)
        .flatMap(issueTemp2-> {
            issue.setSummary(issueTemp2.getSummary());
            return Mono.just(issue); // Return here but you are ignoring this return value
        }).log();
    issueList.add(issue);
});

你应该使用更多的函数来划分你的代码。通过编写函数来养成习惯,并始终从 return 语句开始。您的代码很难阅读。

我认为您应该改用 FLux 而不是迭代流。

// something like the following i'm writing by free hand without IDE
// i have no idea what your logic looks like but you should get the point.
Flux.fromIterable(response.getIssues())
   .flatMap(issue -> {
       return getIssue(issue.getId())
           .flatMap(response -> {
               return issue.setSummary(reponse.getSummary());
           });
   }).collectList();
于 2020-05-04T09:28:25.813 回答