Skip to content

Instantly share code, notes, and snippets.

@xxKRASHxx
Last active December 7, 2018 10:41
Show Gist options
  • Save xxKRASHxx/1b89cf8f70031e8e26b2943460a0c9d6 to your computer and use it in GitHub Desktop.
Save xxKRASHxx/1b89cf8f70031e8e26b2943460a0c9d6 to your computer and use it in GitHub Desktop.
Redux Store
protocol Dispatcher {
func dispatch(action: Action)
}
extension Dispatcher {
func bind(action: Action) -> Command {
return Command { self.dispatch(action: action) }
}
}
import Foundation
final class Store: Dispatcher {
private var state: State {
didSet { self.observers.forEach { $0.perform(with: self.state) } }
}
private var observers: Set<CommandWith<State>> = []
private var middleware: Set<CommandWith<(State, Action, State)>> = []
private let queue = DispatchQueue(label: "store private queue")
private let observationQueue = DispatchQueue(label: "store observation queue")
init(state: State) {
self.state = state
}
func dispatch(action: Action) {
dispatch(actions: [action])
}
func dispatch(actions: [Action]) {
queue.async {
self.state = actions.reduce(self.state) { state, action in
let newState = reduce(state: state, action)
self.middleware.forEach { $0.perform(with: (state, action, newState)) }
return newState
}
}
}
@discardableResult
func addObserver(command: CommandWith<State>) -> Command {
let command = command.dispatched(on: observationQueue)
queue.async {
self.observers.insert(command)
command.perform(with: self.state)
}
return Command { [weak command] in
guard let command = command else {
return
}
self.queue.async {
self.observers.remove(command)
}
}
}
@discardableResult
func addMiddleware(command: CommandWith<(State, Action, State)>) -> Command {
let command = command.dispatched(on: observationQueue)
queue.async {
self.middleware.insert(command)
}
return Command { [weak command] in
guard let command = command else {
return
}
self.queue.async {
self.middleware.remove(command)
}
}
}
func getState() -> State {
return queue.sync { return state }
}
}
extension Store {
func apply<T>(_ actionCreator: @escaping (T) -> Action?) -> (T) -> Void {
return { actionCreator($0).flatMap(self.bind)?.perform() }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment