Skip to content

Instantly share code, notes, and snippets.

@fpg1503
Last active October 17, 2017 01:11
Show Gist options
  • Save fpg1503/a5911852eb5bfff7e35c7b17d15c823d to your computer and use it in GitHub Desktop.
Save fpg1503/a5911852eb5bfff7e35c7b17d15c823d to your computer and use it in GitHub Desktop.
[WIP] Promises from scratch
import Foundation
import PlaygroundSupport
enum PromiseState<T> {
case pending
case fulfilled(T)
case rejected(Error)
var isPending: Bool {
switch self {
case .pending: return true
default: return false
}
}
}
class Promise<T> {
typealias Resolve = (T) -> Void
typealias Reject = (Error) -> Void
typealias ResolveOrReject = (_ resolve: @escaping Resolve, _ reject: @escaping Reject) -> Void
var state: PromiseState<T> {
didSet {
guard oldValue.isPending,
!state.isPending else {
print("Attempt to go from \(oldValue) to \(state), which is an invalid transition, reverting")
state = oldValue
return
}
handlePendencies()
}
}
func handlePendencies() {
switch state {
case .pending: break //Nothing to do here
case .fulfilled(let value):
if !pendencies.isEmpty {
pendencies.forEach { $0(value) }
pendencies = []
}
case .rejected(let error): print(error)
}
}
func resolver(_ newValue: T) -> Void {
self.state = .fulfilled(newValue)
}
func rejecter(_ error: Error) -> Void {
self.state = .rejected(error)
print(error)
}
init(_ resolveOrReject: ResolveOrReject) {
self.state = .pending
resolveOrReject(resolver, rejecter)
}
var pendencies: [(T) -> Void] = [] {
didSet {
handlePendencies()
}
}
func then<U>(transformer: @escaping (T) -> U) -> Promise<U> {
return Promise<U>() { (resolve, reject) in
let resolved: (T) -> Void = { resolvedValue in
let transformed = transformer(resolvedValue)
resolve(transformed)
}
pendencies.append(resolved)
}
}
}
struct TestError: Error { }
let promise = Promise<Int>() { resolve, reject in
resolve(2)
resolve(3)
reject(TestError())
}
promise.then {
print($0)
}
promise.then {
print("Value: \($0)")
}
let foo = Promise({ (resolve, reject) in
DispatchQueue(label: "Test").asyncAfter(deadline: .now() + 0.5, execute: {
resolve(1)
})
}).then {
print($0)
}
print("created promise")
PlaygroundPage.current.needsIndefiniteExecution = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment