【Reactor学习-一 CallBack与Reactor——阻塞代码和非阻塞反应式代码对比】

场景需求: 
	通过用户id获取用户的收藏列表
	如果用户收藏列表为空,显示5条建议收藏记录
	如果不为空显示5条用户收藏记录

阻塞式代码例子(回调地狱 callback hell)

userService.getFavorites(userId, new Callback<List<String>>() {  
	//1. 请求用户收藏列表 请求回调
  public void onSuccess(List<String> list) { // 2
    if (list.isEmpty()) { // 3
      suggestionService.getSuggestions(new Callback<List<Favorite>>() { //4
	  //2. 用户收藏为空,请求5条推荐收藏 再次请求回调
        public void onSuccess(List<Favorite> list) { 
          UiUtils.submitOnUiThread(() -> { // 5. 推送前台
            list.stream()
                .limit(5)  
                .forEach(uiList::show); // 6. 返回五条推荐并在ui线程中显示
            });
        }

        public void onError(Throwable error) { //7
          UiUtils.errorPopup(error);
        }
      });
    } else {
      list.stream() //8 获取收藏列表5个记录id
          .limit(5)
          .forEach(favId -> favoriteService.getDetails(favId, 
            new Callback<Favorite>() {  //9 再次回调,返回内容详情
              public void onSuccess(Favorite details) {
                UiUtils.submitOnUiThread(() -> uiList.show(details));
              }

              public void onError(Throwable error) {
                UiUtils.errorPopup(error);
              }
            }
          ));
    }
  }

  public void onError(Throwable error) {
    UiUtils.errorPopup(error);
  }
});
分析
1.我们有基于回调的服务:一个回调接口,在异步进程成功时调用一个方法,在发生错误时调用一个方法。
2.第一个服务使用常用ID列表调用其回调。
3.如果列表为空,我们必须转到建议服务。
4.suggestionService向第二次回调提供一个列表<Favorite>。
5.因为我们处理的是UI,所以我们需要确保我们的消费代码在UI线程中运行。
6.我们使用Java 8流将处理的建议数量限制为五个,并在UI的图形列表中显示它们。
7.在每个级别,我们处理错误的方式都是一样的:我们在弹出窗口中显示错误。
8.回到收藏ID级别。如果服务返回完整列表,我们需要转到favoriteService以获取详细的收藏夹对象。因为我们只需要五个,所以我们首先流式处理ID列表,将其限制为五个。
9.再次回复。这一次,我们得到了一个完全成熟的最喜欢的对象,我们将其推送到UI线程内的UI。

缺点很明细,代码量大,不易跟踪,代码重复,对比响应式代码来实现相同功能。

反应式代码对比回调代码

userService.getFavorites(userId) //1.
           .flatMap(favoriteService::getDetails) //2. 
           .switchIfEmpty(suggestionService.getSuggestions()) //3.
           .take(5) //4.
           .publishOn(UiUtils.uiThreadScheduler()) //5.
           .subscribe(uiList::show, UiUtils::errorPopup); //6. 
分析
1.我们根据用户ID获得收藏开始。
2.我们将这些对象转换为异步的常用对象(flatMap)。我们现在有了收藏的列表。
3.如果收藏夹流为空,我们将通过suggestionService切换到备用。
4.我们最多只对结果流中的五个元素感兴趣。
5.最后,我们希望处理UI线程中的每一条数据。
6.我们通过描述如何处理最终形式的数据(在UI列表中显示)以及发生错误时如何处理(显示弹出窗口)来触发响应式流

如果要确保在不到800毫秒的时间内检索到收藏的ID,或者如果需要更长时间,从缓存中获取它们,该怎么办?在基于回调的代码中,这是一项复杂的任务。在Reactor中,只需在链中添加一个超时操作符即可,如下所示:。

userService.getFavorites(userId)
           .timeout(Duration.ofMillis(800))  // 1. 
           .onErrorResume(cacheService.cachedFavoritesFor(userId)) //2.
           .flatMap(favoriteService::getDetails)   //3. 
           .switchIfEmpty(suggestionService.getSuggestions())
           .take(5)
           .publishOn(UiUtils.uiThreadScheduler())
           .subscribe(uiList::show, UiUtils::errorPopup);
分析
1.如果上述部件在超过800ms的时间内无任何辐射,则传播错误。
2.如果出现错误,请返回缓存服务。
3.链的其余部分与上一个示例类似。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dangkei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值