如何使用ReSwift派发带参数(payload)的异步Action?
如何给ReSwift的异步Action传递参数?
嘿,这个问题我之前也碰到过,其实只要稍微调整一下异步Action的写法就能解决,给你两种实用的方案:
方案一:函数柯里化(快速适配现有代码)
你可以把原来的searchItems改成先接收参数,再返回符合ReSwift要求的异步Action闭包,这样就能在派发的时候传入搜索词了。修改后的代码如下:
// 先接收搜索词参数,再返回异步Action闭包 func searchItems(withTerm term: String) -> (AppState, Store<AppState>) -> Action? { return { state, store in var items = [Artwork]() // 这里直接用传入的term参数发起请求 HttpHelper.post(url: serverApi.search.rawValue, params: ["term": term]) { data in if let data = data as? [[String: Any]] { for row in data { items.append(Artwork(data: row)) } DispatchQueue.main.async { store.dispatch(UpdateItems(items: items)) } } } return nil } }
派发的时候就可以直接传搜索词了:
// 示例:传入"梵高"作为搜索词 store.dispatch(searchItems(withTerm: "梵高"))
这种方式的核心是利用了Swift的函数柯里化特性,先把需要的参数“存”起来,再返回ReSwift能识别的异步Action类型,改动很小,适合快速适配你的现有代码。
方案二:自定义异步Action + Middleware(更规范的架构方案)
如果你的应用里有很多异步操作,推荐用这种方式——把异步逻辑放到Middleware里,Action只负责携带参数,这样代码结构会更清晰,也符合ReSwift的设计思想。
步骤1:定义带参数的异步Action
// 遵循ReSwift的Action协议,把搜索词作为属性 struct SearchItemsAction: Action { let term: String }
步骤2:编写处理该Action的Middleware
let searchMiddleware: Middleware<AppState> = { dispatch, getState in return { next in return { action in // 判断当前Action是不是我们定义的SearchItemsAction if let searchAction = action as? SearchItemsAction { var items = [Artwork]() // 使用Action里的term参数发起请求 HttpHelper.post(url: serverApi.search.rawValue, params: ["term": searchAction.term]) { data in if let data = data as? [[String: Any]] { for row in data { items.append(Artwork(data: row)) } DispatchQueue.main.async { // 请求完成后派发同步的UpdateItems Action dispatch(UpdateItems(items: items)) } } } // 这个异步Action不需要传给Reducer,直接返回 return } // 其他普通Action继续传递给下一个Middleware或Reducer next(action) } } }
步骤3:创建Store时加入Middleware
let store = Store<AppState>( reducer: appReducer, state: nil, middleware: [searchMiddleware] // 把刚才写的middleware加进来 )
步骤4:派发带参数的Action
store.dispatch(SearchItemsAction(term: "莫奈"))
这种方案的好处是把异步逻辑和Action解耦了,所有异步操作都可以集中在Middleware里管理,后期维护和扩展会更方便。
内容的提问来源于stack exchange,提问作者Julian Gong
相关产品推荐
相关产品推荐

