三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

SwiftUIFlux中间件机制揭秘:从源码理解middleware链式调用的工作原理

SwiftUIFlux中间件机制揭秘:从源码理解middleware链式调用的工作原理

SwiftUIFlux中间件机制揭秘:从源码理解middleware链式调用的工作原理

【免费下载链接】SwiftUIFluxA very naive implementation of Redux using Combine BindableObject to serve as an example项目地址: https://gitcode.com/gh_mirrors/sw/SwiftUIFlux

SwiftUIFlux 是一个基于 SwiftUI 与 Combine 实现的轻量级 Redux 状态管理库,其最精妙的设计之一就是中间件机制(middleware)。本文将带你从源码出发,一步步拆解 SwiftUIFlux 中间件链式调用的完整工作原理,帮助你彻底搞懂 Action 是如何被"层层加工"后最终交给 Reducer 处理的。无论你是 SwiftUI 新手还是想深入理解 Flux 架构的开发者,这篇 SwiftUIFlux 源码解析都能让你快速上手。

一、为什么要设计中间件?它解决了什么问题?

在纯 Redux 架构中,数据流是单向且同步的:视图派发 Action → Reducer 计算新状态 → 视图刷新。但真实业务里我们常需要异步请求、日志记录、状态上报等副作用操作。SwiftUIFlux 通过middleware 中间件在 Action 到达 Reducer 之前插入一层"拦截管道",让这些副作用有了合适的栖身之所。

二、中间件的核心定义:三段式函数签名

打开源码Sources/SwiftUIFlux/protocols/Middleware.swift,你会发现中间件的类型定义非常精炼:

public typealias Middleware<State> = (@escaping DispatchFunction, @escaping () -> FluxState?) -> (@escaping DispatchFunction) -> DispatchFunction

这个签名本质是柯里化的三层嵌套函数

  • 第一层接收dispatch(派发函数)和getState(获取状态闭包),用于执行副作用;
  • 第二层接收next(下一个中间件或最终的 Reducer 派发函数),用于接力;
  • 第三层接收action,这是真正处理 Action 的入口,处理完必须调用next(action)放行。

正是这种"返回函数再返回函数"的结构,为middleware 链式调用奠定了语法基础。

三、链式调用如何组装?核心在于 Store 的 reduce 技巧

要理解 SwiftUIFlux 中间件机制,关键在Sources/SwiftUIFlux/Store.swiftinit方法。Store 初始化时会自动把内置的asyncActionsMiddleware追加到你的中间件数组末尾,然后执行一段非常优雅的组装逻辑:

middleware.append(asyncActionsMiddleware) self.dispatchFunction = middleware .reversed() .reduce(初始派发函数) { dispatchFunction, middleware in return middleware(dispatch, getState)(dispatchFunction) }

这里有两个容易忽略的细节:

  1. reversed()反转数组:因为reduce是从右往左折叠,反转后才能保证数组第一个中间件处于管道最外层;
  2. 初始值是"裸"派发函数:即最终调用reducer(state, action)的那一步,它作为整条链的终点。

组装完成后,你调用store.dispatch(action:)时,Action 会按"中间件1 → 中间件2 → … → 内置异步中间件 → Reducer"的顺序依次穿过整条链路。

四、图解 Action 在中间件管道中的流转路径

视图 dispatch(action) │ ▼ ┌─────────────────────────────────────────┐ │ 中间件1(日志/埋点) │ │ 调用 next(action) 放行 │ └─────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ 中间件2(自定义业务拦截) │ │ 调用 next(action) 放行 │ └─────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ asyncActionsMiddleware(内置异步中间件) │ │ 拦截 AsyncAction 并执行异步任务 │ └─────────────────────────────────────────┘ │ ▼ Reducer 计算新状态

每个中间件都握有next这把"接力棒",只有调用next(action)数据流才会继续向下传递,这给了开发者极大的控制权:可以拦截、改写、延迟甚至丢弃某些 Action。

五、内置异步中间件源码逐行解读

Sources/SwiftUIFlux/middleware/AsyncActionsMiddleware.swift是整个库唯一的官方中间件,代码只有十几行,却完整展示了中间件的标准写法:

public let asyncActionsMiddleware: Middleware<FluxState> = { dispatch, getState in return { next in return { action in if let action = action as? AsyncAction { action.execute(state: getState(), dispatch: dispatch) } return next(action) } } }

它的工作逻辑非常清晰:

  1. 判断传入的 Action 是否遵循AsyncAction协议;
  2. 若是,则执行action.execute(state:dispatch:)启动异步任务(比如网络请求);
  3. 无论是否拦截,最终都调用next(action)把 Action 继续传给 Reducer。

配合Sources/SwiftUIFlux/protocols/AsyncAction.swift中定义的协议,你可以在execute方法里发起网络请求,并在回调中再次dispatch新的 Action 来更新状态,从而优雅地实现异步数据流。

六、中间件链式调用的三个易错点与最佳实践

1. 必须显式调用next(action)忘记调用next会直接掐断数据流,导致 Reducer 收不到 Action、状态永远不更新。这是新手最容易踩的坑。

2. 中间件的顺序会影响行为数组靠前的中间件处于外层、更早拿到 Action。若需要"后写的先执行",记得调整数组顺序或利用reversed()的特性。

3. 副作用不要写在 Reducer 里保持 Reducer 纯函数特性,把所有网络请求、日志、埋点统一收敛到 middleware 中,这才是 SwiftUIFlux 中间件机制设计的初衷。

七、总结:一图记住 SwiftUIFlux 中间件机制

SwiftUIFlux 的中间件机制可以用一句话概括:用柯里化函数 + reduce 折叠,把多个中间件串成一条单向管道,Action 依次穿过管道最终抵达 Reducer。理解了Middleware.swift的类型签名与Store.swift的组装逻辑,你就能随心所欲地扩展自己的中间件,打造专属的 SwiftUI 状态管理方案。

如果你想动手实验,建议 clone 源码后重点阅读Sources/SwiftUIFlux/Store.swiftSources/SwiftUIFlux/protocols/Middleware.swiftSources/SwiftUIFlux/middleware/AsyncActionsMiddleware.swift三个文件,再仿照内置异步中间件编写一个日志中间件,你会对 SwiftUIFlux 中间件链式调用有更直观的体感。

【免费下载链接】SwiftUIFluxA very naive implementation of Redux using Combine BindableObject to serve as an example项目地址: https://gitcode.com/gh_mirrors/sw/SwiftUIFlux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

← 返回列表