基于Kotlin中Flow扩展重试方法

news2025/2/12 11:35:15

在这里插入图片描述
最近项目中统一采用Kotlin的Flow来重构了网络请求相关代码。
目前的场景是,接口在请求的时候需要一个accessToken值,因为此值会过期或者不存在,需要刷新,因此最终方案是在使用Flow请求的时候先获取accessToken值然后再进行接口请求,而获取accessToken值的方法已经封装成了一个Flow并且做了缓存,因此最后需要使用flatMapConcat操作符来连接真正需要的接口请求,如果获取的accessToken无效,又需要回头重新执行,逻辑如下:

  1. 判断本地是否存在accessToken并且是否过期,不存在或者已过期则请求accessToken
  2. 请求对应的接口
  3. 如果返回结果中accessToken无效,则重试

Flow提供了retryretryWhen两种扩展方法来做重试操作:

retry源码

public fun <T> Flow<T>.retry(
    retries: Long = Long.MAX_VALUE,
    predicate: suspend (cause: Throwable) -> Boolean = { true }
): Flow<T> {
    require(retries > 0) { "Expected positive amount of retries, but had $retries" }
    return retryWhen { cause, attempt -> attempt < retries && predicate(cause) }
}

retryWhen源码

public fun <T> Flow<T>.retryWhen(predicate: suspend FlowCollector<T>.(cause: Throwable, attempt: Long) -> Boolean): Flow<T> =
    flow {
        var attempt = 0L
        var shallRetry: Boolean
        do {
            shallRetry = false
            val cause = catchImpl(this)
            if (cause != null) {
                if (predicate(cause, attempt)) {
                    shallRetry = true
                    attempt++
                } else {
                    throw cause
                }
            }
        } while (shallRetry)
    }

但是,retryretryWhen只能通过异常来判断,如果是通过返回结果来判断,就需要借助外部变量来处理了,因此基于源码扩展了方法retry,可以接收请求结果,从而通过请求结果来判断是否需要重试。

fun <T> Flow<T>.retry(
    retries: Long = Long.MAX_VALUE, predicate: suspend (result: T) -> Boolean = { true }
): Flow<T> {
    require(retries > 0) { "Expected positive amount of retries, but had $retries" }
    return flow {
        var attempt = 0L
        var shallRetry: Boolean
        do {
            shallRetry = false
            try {
                collect {
                    if (attempt < retries && predicate(it)) {
                        shallRetry = true
                        attempt++
                    } else {
                        this.emit(it)
                    }
                }
            } catch (e: Throwable) {
                throw e
            }
        } while (shallRetry)
    }
}

最后的请求示例代码如下:

MainScope().launch {
        getToken().flatMapConcat {
            if (it is Result.Success) {
                sendMobileCode()
            } else {
                emptyFlow()
            }
        }.retry(1) {
            return@retry (it is Result.Failure) && (it.code == ErrorStatus.ACCESS_TOKEN_ERROR)
        }.flowOn(Dispatchers.IO).onStart {
            callback?.onStart()
        }.catch {
            callback?.onError(it)
        }.onCompletion {
            callback?.onComplete(it)
        }.collectLatest { result ->
        }
    }

感谢大家的支持,如有错误请指正,如需转载请标明原文出处!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296802.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

oracle如何查询历史最大进程数?

oracle如何查询历史最大进程数&#xff1f; SQL> desc dba_hist_resource_limitName Null? Type---------------------------------------------------- -------- ------------------------------------SNAP_ID …

利用HTML和css技术编写学校官网页面

目录 一&#xff0c;图例展示 二&#xff0c;代码说明 1&#xff0c;html部分&#xff1a; 【第一张图片】 【第二张图片】 【第三张图片】 2&#xff0c;css部分&#xff1a; 【第一张图片】 【第二张图片】 【第三张图片】 三&#xff0c;程序代码 一&#xff0c;…

Flink KafkaConsumer offset是如何提交的

一、fllink 内部配置 client.id.prefix&#xff0c;指定用于 Kafka Consumer 的客户端 ID 前缀partition.discovery.interval.ms&#xff0c;定义 Kafka Source 检查新分区的时间间隔。 请参阅下面的动态分区检查一节register.consumer.metrics 指定是否在 Flink 中注册 Kafka…

拯救者Y9000P双系统ubuntu22.04安装4070显卡驱动

拯救者Y9000P双系统ubuntu22.04安装4070显卡驱动 1. 前情&#xff1a; 1TB的硬盘&#xff0c;分了120G作ubuntu22.04。/boot: 300MB, / : 40GB, /home: 75G, 其余作swap area。 2. 一开始按这个教程&#xff1a;对我无效 https://blog.csdn.net/Eric_xkk/article/details/1…

Web3 的虚实融合之路:从虚拟交互到元宇宙构建

在这个数字技术日新月异的时代&#xff0c;我们正站在 Web3 的门槛上&#xff0c;见证着互联网的又一次革命。Web3 不仅仅是技术的迭代&#xff0c;它代表了一种全新的交互方式和价值创造模式。本文将探讨 Web3 如何推动虚拟交互的发展&#xff0c;并最终实现元宇宙的构建&…

QT修仙笔记 事件大圆满 闹钟大成

学习笔记 牛客刷题 闹钟 时钟显示 通过 QTimer 每秒更新一次 QLCDNumber 显示的当前时间&#xff0c;格式为 hh:mm:ss&#xff0c;实现实时时钟显示。 闹钟设置 使用 QDateTimeEdit 让用户设置闹钟时间&#xff0c;可通过日历选择日期&#xff0c;设置范围为当前时间到未来 …

2025 年 2 月 TIOBE 指数

2025 年 2 月 TIOBE 指数 二月头条:快,更快,最快! 现在,世界需要每秒处理越来越多的数字,而硬件的发展速度却不够快,程序的速度变得越来越重要。话虽如此,快速编程语言在 TIOBE 指数中取得进展也就不足为奇了。编程语言 C++ 最近攀升至第 2 位,Go 已稳居前 10 名,Ru…

防火墙是什么?详解网络安全的关键守护者

当今信息化时代&#xff0c;企业和个人在享受数字生活带来的便利时&#xff0c;也不可避免地面对各种潜在的风险。防火墙作为网络安全体系中的核心组件&#xff0c;就像一道牢不可破的防线&#xff0c;保护着我们的数据和隐私不受外界威胁的侵害。那么防火墙是什么&#xff1f;…

第三篇:半导体“红蓝药丸“——IGBT/SiC器件如何重塑电驱系统

副标题&#xff1a;当黑客帝国遇见800V高压架构&#xff0c;第三代半导体开启能源革命 ▶ 开篇&#xff1a;红蓝药丸的终极抉择 黑客帝国隐喻 - 红色药丸&#xff08;IGBT&#xff09; &#xff1a;传统硅基器件构建的"真实世界"——成熟稳定但存在性能天花板…

VTK编程指南<十六>:VTK表面重建之Delaunay三角剖分

1、无边界限制 三角剖分是一种应用非常广泛的重建技术。三角剖分将一些散乱的点云数据划分为一系列的三角形网格。最常用的三角剖分技术是Delaunay三角剖分。Delaunay三角剖分具有许多优良的性质&#xff0c;即最大化最小角特性&#xff0c;即所有可能的三角形剖分中&#xff0…

2.Excel:滨海市重点中学的物理统考考试情况❗(15)

目录 NO12​ 1.数据透视表​ 2. 3.sum函数 4.sumifs客观/主观平均分​ 5.sumifs得分率​ 6.数字格式修改​ NO3/4/5​ sumifs某一组数据相加&#xff0c;某一范围&#xff0c;某一范围的具体点向下拖拉&#xff0c;锁定列&#xff1b;向左右&#xff0c;锁定行F4&#x…

Hdoop之MapReduce的原理

简单版本 AppMaster: 整个Job任务的核心协调工具 MapTask: 主要用于Map任务的执行 ReduceTask: 主要用于Reduce任务的执行 一个任务提交Job --> AppMaster(项目经理)--> 根据切片的数量统计出需要多少个MapTask任务 --> 向ResourceManager(Yarn平台的老大)索要资源 --…

JAVA并发编程3--多线程程序

​ 1.创建线程的方法&#xff1a; 案例&#xff1a;计算1-1000的整数和 实现Runnable接口 步骤&#xff1a; 1.创建一个实现了Runnable接口的类 2.实现类去实现Runnable中的抽象方法&#xff1a;run() 3.创建实现类的对象 4.将此对象作为参数传递到Thread类的构造器中&#…

自主项目面试点总结

1、许苑–OJ判题系统 技术栈&#xff1a;Spring BootSpring Cloud AlibabaRedisMybatisMQDocker 项目地址: https://github.com/xuyuan-upward/xyoj-backend-microservice 1.1、项目介绍: 一个基于微服务的OJ系统&#xff0c;具备能够根据管理员预设的题目用例对用户提交的代…

idea Ai工具通义灵码,Copilot我的使用方法以及比较

我用过多个idea Ai 编程工具&#xff0c;大约用了1年时间&#xff0c;来体会他们那个好用&#xff0c;以下只是针对我个人的一点分享&#xff0c;不一定对你适用 仅作参考。 介于篇幅原因我觉得能说上好用的 目前只有两个 一个是阿里的通义灵码和Copilot&#xff0c;我用它来干…

4.python基础语法-下

文章目录 1.顺序语句2.条件语句 - if2.1什么是条件语句2.2语法格式2.2.1if2.2.2if - else2.2.3if - elif - else 2.3缩进和代码块2.4练习2.5空语句 pass 3.循环语句3.1while循环3.2for循环3.3continue3.4break 4.综合案例4.1设置初始属性4.2设置性别4.3设置出生点4.4针对每一岁…

Java--集合(理论)

目录 一、collection collection常用方法 1.List&#xff08;可以存在重复元素&#xff09; 迭代器 迭代器的概念 注意事项 例子 1.ArrayList 特点 2.LinkedLIst 特点 3.Vector 特点 2.Set&#xff08;无重复元素&#xff09; 1.HashSet 特点 2.Linkedhashset&…

3D图形学与可视化大屏: 3D 图形学的定义、应用领域和发展历程

一、3D 图形学的定义 3D 图形学是计算机科学的一个分支&#xff0c;主要研究如何在计算机上生成、处理和显示三维图形。它涉及到数学、物理学、计算机科学等多个学科领域&#xff0c;旨在通过计算机技术模拟真实世界中的三维物体和场景&#xff0c;为用户提供逼真的视觉体验。…

Python 面向对象(类,对象,方法,属性,魔术方法)

前言&#xff1a;在讲面向对象之前&#xff0c;我们先将面向过程和面向对象进行一个简单的分析比较&#xff0c;这样我们可以更好的理解与区分&#xff0c;然后我们在详细的讲解面向对象的优势。 面向过程&#xff08;Procedure-Oriented Programming&#xff0c;POP&#xff0…

轮子项目--消息队列的实现(3)

上一篇文章中我把一些关键的类以及表示出来&#xff0c;如何对这些类对应的对象进行管理呢&#xff1f;管理分为硬盘和内存上&#xff0c;硬盘又分为数据库&#xff08;管理交换机&#xff0c;队列和绑定&#xff09;和文件&#xff08;管理消息&#xff09;&#xff0c;本文就…