Last active
December 7, 2018 10:41
-
-
Save xxKRASHxx/1b89cf8f70031e8e26b2943460a0c9d6 to your computer and use it in GitHub Desktop.
Redux Store
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol Dispatcher { | |
func dispatch(action: Action) | |
} | |
extension Dispatcher { | |
func bind(action: Action) -> Command { | |
return Command { self.dispatch(action: action) } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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