可观察,出错时重试并仅在完成时缓存

2024-03-28

我们可以使用cache()运算符来避免多次执行长任务(http请求),并重用其结果:

Observable apiCall = createApiCallObservable().cache(); // notice the .cache()

---------------------------------------------
// the first time we need it
apiCall.andSomeOtherStuff()
               .subscribe(subscriberA);

---------------------------------------------
//in the future when we need it again
apiCall.andSomeDifferentStuff()
               .subscribe(subscriberB);

第一次执行http请求,但第二次,因为我们使用了cache()运算符,请求将不会被执行,但我们将能够重用第一个结果。

当第一个请求成功完成时,这工作正常。但是,如果在第一次尝试中调用 onError ,那么下次新订阅者订阅同一个可观察值时,将再次调用 onError ,而无需再次尝试 http 请求。

我们想要做的是,如果第一次调用 onError,那么下次有人订阅同一个可观察对象时,将从头开始尝试 http 请求。即 observable 将仅缓存成功的 api 调用,即调用 onCompleted 的那些调用。

关于如何继续的任何想法?我们尝试过使用 retry() 和 cache() 运算符,但运气不佳。


这是我们在扩展 akarnokd 的解决方案后最终得到的解决方案:

public class OnErrorRetryCache<T> {

    public static <T> Observable<T> from(Observable<T> source) {
         return new OnErrorRetryCache<>(source).deferred;
    }

    private final Observable<T> deferred;
    private final Semaphore singlePermit = new Semaphore(1);

    private Observable<T> cache = null;
    private Observable<T> inProgress = null;

    private OnErrorRetryCache(Observable<T> source) {
        deferred = Observable.defer(() -> createWhenObserverSubscribes(source));
    }

    private Observable<T> createWhenObserverSubscribes(Observable<T> source) 
    {
        singlePermit.acquireUninterruptibly();

        Observable<T> cached = cache;
        if (cached != null) {
            singlePermit.release();
            return cached;
        }

        inProgress = source
                .doOnCompleted(this::onSuccess)
                .doOnTerminate(this::onTermination)
                .replay()
                .autoConnect();

        return inProgress;
    }

    private void onSuccess() {
        cache = inProgress;
    }

    private void onTermination() {
        inProgress = null;
        singlePermit.release();
    }
}

我们需要缓存来自 Retrofit 的 http 请求的结果。因此,它被创建了,并带有一个发出单个项目的可观察对象。

如果观察者在执行 http 请求时订阅,我们希望它等待并且不会执行该请求两次,除非正在进行的请求失败。为此,信号量允许对创建或返回缓存的可观察量的块进行单次访问,​​如果创建了新的可观察量,我们将等待该可观察量终止。对以上内容进行测试可以发现here https://github.com/platoblm/rx-onerror-retry-cache/blob/master/src/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可观察,出错时重试并仅在完成时缓存 的相关文章

  • 立即交付第一个项目,“消除”后续项目

    考虑以下用例 需要尽快交付第一个项目 need to debounce以下事件有 1 秒超时 我最终实现了基于的自定义运算符OperatorDebounceWithTime然后像这样使用它 lift new CustomOperatorDe
  • RxJava API 和 Java 9 Flow API 之间的区别

    在过去几个主要版本的 Java 的每次迭代中 似乎都有一致的新方法来管理并发任务 在 Java 9 中 我们有Flow API https docs oracle com javase 9 docs api index html java
  • 在 android 中使用 RxJava 和 Retrofit 处理列表

    我需要进行几个 api 调用 顺序 异步 其中一些返回列表 我的api接口如下 GET users settings Observable
  • Spinner 的 RxBindings?

    我是新的 android 和 rxjava 我经历过很多使用 rxbindings 监听事件的例子 比如这个 RxView clicks b subscribe new Action1
  • subject.asObservable 有什么用?

    为什么需要RxJavaasObservable 从技术上讲 每个主题都已经是一个可观察的 它比仅仅铸造它有什么优势 Observable obs subject 如果你只是投Subject to an Observable那么你仍然可以使用
  • RxJava,一个可观察多个订阅者:publish().autoConnect()

    我正在使用 rxJava rxAndroid 但有一些非常基本的东西没有按照我的预期运行 我有一个可观察对象和两个订阅者 Observable
  • 如何在 RxJava 中计算移动平均线

    在金融领域 我们通常需要从时间序列数据流中计算移动窗口总值 以移动平均线为例 假设我们有以下数据流 T是时间戳 V是实际值 T0 V0 T1 V1 T2 V2 T3 V3 T4 V4 T5 V5 T6 V6 T7 V7 T8 V8 T9 V
  • RxJava 并行获取 Observables

    我需要一些帮助来在 RxJava 中实现并行异步调用 我选择了一个简单的用例 其中第一个调用获取 而不是搜索 要显示的产品列表 平铺 随后的调用将获取 A 评论和 B 产品图像 经过几次尝试我到达了这个地方 1 Observable
  • 使用 Retrofit observable 处理网络错误

    当将 Observables 与 Retrofit 结合使用时 如何处理网络故障 鉴于此代码 Observable
  • Rx 2 Android 对于 api 调用,Single 或 Observable 哪个更好?

    当我们使用 Retrofit2 通过 Rx 进行 API Rest 调用时 最好的使用方法是什么 单一还是可观察 public interface ApiService Single
  • 为什么我的 RxJava Flowable 在使用observeOn 时不考虑背压?

    我正在尝试创建一个Flowable它会发出有关背压的事件以避免内存问题 同时并行运行转换的每个阶段以提高效率 我创建了一个简单的测试程序来推理程序不同步骤的行为以及何时发出事件与在不同阶段等待事件 我的程序如下 public static
  • 实现 retryWhen 逻辑

    我有一个需要会话 cookie 来处理网络调用的应用程序 我在用着Retrofit RxJava 但是 会话可能会过期 带有 401 未经授权状态的改造错误 在这种情况下我想重新进行身份验证 以获取新的 cookie 并重试之前的调用 我该
  • 如何在改造多部分请求中发送对象数组

    I want to send array objects with multipart data I tried many ways but it is not working My issue with the contributor p
  • RxJava + 改造,获取列表并为每个项目添加额外信息

    我正在玩 RXJava 在 Android 中进行改造 我正在努力完成以下任务 我需要定期轮询一个给我 Observable gt 的调用 从这里我可以做到 一旦我得到这个列表 我想在每个交付中迭代并调用另一个方法来给我预计到达时间 所以只
  • 如何使用 Retrofit 和 RxJava/RxAndroid 处理响应错误?

    我无法弄清楚如何使用改造和 RxAndroid 处理响应错误 如果存在网络错误等 则会调用 onError 但我需要能够获取响应以检查是否存在身份验证错误 相反 我得到的是一个带有空字符串的令牌 但我找不到原因 解决这个问题的最佳方法是什么
  • RxJava 作为事件总线?

    我开始学习 RxJava 到目前为止我很喜欢它 我有一个片段与单击按钮时的活动进行通信 用新片段替换当前片段 谷歌推荐界面 http developer android com training basics fragments commu
  • RxJava 中的笛卡尔积

    是否有可能在rxjava中获得两个Observables的笛卡尔积 像这样的事情 A gt 1 2 3 B gt a b A x B gt 1 a 1 b 2 a 2 b 3 a 3 b 你想要的是 对于一个数字 产生与你有字母一样的一对
  • RxJava 中的 n 元笛卡尔积

    现在我持有一个Observable
  • Java反应式框架的比较[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我看到许多框架 库声称它们可以帮助用 Java 构建响应式应用程序 例如 Akka Vert x RxJava Reactor QBit 等 他
  • 在 RxJava 中,如何在错误时重试/恢复,而不是完成可观察的

    我想要实现的是 监控特定变化的偏好 当检测到更改时 使用新值启动新的网络调用 变换结果 在 UI 中显示结果 我知道更改何时发生 现在我认为我需要对某个主题调用 onNext 然后这应该会触发 Rx 链 最后我可以更新 UI mViewPe

随机推荐

  • Windows 7 操作中心

    如果有人可以指导我修改 控制 Windows 7 操作中心所需的新 MS API 我将不胜感激 我需要做的是将备份通知消息集成到我的应用程序中 该应用程序是操作中心的备份应用程序 换句话说 我希望Windows在第三方软件完成备份操作后显示
  • 使用 jQuery 从 'a' 元素的 'href' 属性中剪切文件名的最佳方法是什么?

    例如我有简单的代码 ul class list li a href http www aaa com bbb ccc file01 pdf Download file 01 a li li a href http www bbb com c
  • 我可以删除弹出视图中的箭头吗?

    我被要求删除弹出视图的箭头 这是否违反了人机界面准则 在另一个弹出窗口中显示一个弹出窗口是否明智 如果不违反人机界面准则怎么办 对于斯威夫特 popoverMenuViewController permittedArrowDirection
  • 在 vscode 中将现有 Java 项目转换为 Maven

    我有一个没有任何东西的旧Java项目 我想使用maven 因为缺少一些依赖项并且我找不到库 有人可以告诉我如何将该项目转换为 MavenWITH VSCODE 以下是一些步骤 告诉 VS Code使用Maven https code vis
  • 如何获取最顶层活动的标识符?

    我有一个服务 当最顶层的 Activity 发生变化时 它的行为必须改变 假设 活动 A 处于活动状态 然后服务开始某种处理 当 Activity A 不再可见时 此处理必须停止 用户按下 后退 主页 或执行任何其他操作使 Activity
  • MySQL 记录 UPDATE 应该会失败,但实际上却没有。为什么?

    这是一个有趣的情况 我用 MySQL 开始一个事务 我的交易涉及3个相关查询 每个查询都必须成功 如果没有成功 则不应将任何查询写入数据库 现在 故意 对于第二个查询 这恰好是一个更新查询 我改变了 标识要更新为无效 不存在 PK 值的记录
  • 在散点图中将值绘制为符号的最简单方法?

    在回答我之前关于修复 4D 数据散点图像的色彩空间的问题时 Tom10 建议将值绘制为符号 以便仔细检查我的数据 一个好主意 我过去运行过一些类似的演示 但我一生都找不到我记得的演示非常简单 那么 将数值绘制为散点图中的符号 而不是 o 的
  • IPv6 地址的正则表达式

    我有一个 IPv6 地址的正则表达式 如下所示 IPV4ADDRESS t digit 1 3 3 digit 1 3 t x4 xdigit 1 4 xseq x4 x4 0 7 xpart xseq xseq xseq xseq IPV
  • Scala sbt:sbt 中的多个依赖项

    我是 Scala 的新用户 正在按照创建 scala sbt 项目的方式进行操作 https www youtube com watch v Ok7gYD1VbNw https www youtube com watch v Ok7gYD1
  • 如何在shell中剪切字符串的第一列(可变长度)

    如何在shell中剪切字符串的第一列 可变长度 字符串的前 23006 帮助 txt 我需要 23006 作为输出 很多方法 cut d f1
  • 为什么我的 WebClient 大多数时候会返回 404 错误,但并非总是如此?

    我想要获取有关我的程序中的 Microsoft 更新的信息 但是 服务器在大约 80 的情况下会返回 404 错误 我将有问题的代码归结为这个控制台应用程序 using System using System Net namespace W
  • 实施 Dijkstra 算法

    我的任务是 大学课程 实施某种形式的寻路 现在 在规范中 我可以实现强力 因为要搜索的节点数量有限制 开始 中间两个 结束 但我想重新使用此代码并来实现迪杰斯特拉算法 http en wikipedia org wiki Dijkstra
  • 如何防止android服务被杀死(带通知的服务)

    我正在开发一个需要不断显示通知的应用程序 我有一项服务可以每秒显示一次通知 当资源不足时 android 就会终止我的服务 我已经从 onStartCommand 给出了返回 START STICKY 因此 一段时间后 服务将重新启动 但与
  • 如何创建自定义元素扩展类的新实例

    我正在尝试以下示例谷歌开发者网站 https developers google com web fundamentals getting started primers customelements extendhtml我收到错误 Typ
  • 如何使用 Grunt 为 LESS 配置 sourceMap?

    我正在使用 grunt 0 4 2 和 grunt contrib less 0 9 0 我希望将我的 LESS 编译成 CSS 并支持源映射 我的 LESS 文件位于public less 主要的称为main less 的编译public
  • 无论如何,Bootstrap 导航栏都不会居中

    我一直在尝试使用 Bootstrap 将我的导航栏集中在导航栏的中心 这非常糟糕 我尝试过使用类似问题中的信息 例如this one https stackoverflow com questions 7165423 twitter boo
  • JS hasAttribute 带有数据属性值

    有没有一种原生方法 没有 jQuery 来检查 dom 元素是否具有具有所选值的属性 例如 assume doc has data mod do defined 这将是真的 document hasAttribute data mod 但这
  • Xamarin 表单 - 以流形式打开文件

    这可能是一个非常简单的问题 但当我们谈论流时我总是感到困惑 我正在尝试在 Xamarin Forms 项目的 Android 部分中打开一个文件 我有一个 Java IO File 我想将其转换为流 以便能够使用这个简单的函数将其发送到 A
  • 当一个值的所有者可以读取它而另一个线程更改它时,Rust 如何防止数据竞争?

    Rust 书中指出了以下内容参考文献和借用 https doc rust lang org book ch04 02 references and borrowing html mutable references 当我们有一个不可变的引用
  • 可观察,出错时重试并仅在完成时缓存

    我们可以使用cache 运算符来避免多次执行长任务 http请求 并重用其结果 Observable apiCall createApiCallObservable cache notice the cache the first time