Skip to content

Instantly share code, notes, and snippets.

@benjamingr
Created August 12, 2014 18:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benjamingr/21dda08002b09c930fe6 to your computer and use it in GitHub Desktop.
Save benjamingr/21dda08002b09c930fe6 to your computer and use it in GitHub Desktop.
// compile error
Promise.resolve(15).then({
print("Got2 \($0)")
})
// works
Promise<Any,Any>.resolve(15).then({
print("Got2 \($0)")
})
//
// Promise.swift
// Promise
//
// Created by Benjamin Gruenbaum on 8/12/14.
// Copyright (c) 2014 Tipranks. All rights reserved.
//
import Foundation
public class Promise<T,E>{
var state:PromiseState<T,E> = PromiseState(state: .Pending, value: nil, error: nil)
var fHandlers:[(T) -> ()] = []
var rHandlers:[(E?) -> ()] = []
func getState() -> State{
return self.state.state
}
public func value() -> T?{
return self.state.value;
}
public func reject<E>(t:E) -> Promise<Any,E> {
let p:Promise<Any,E> = Promise<Any,E>()
p.state.state = .Rejected
p.state.error = t
return p
}
// no real need to alias anything, we do not assimilate foreign thenables
//public class func resolve<V,X>(t:Promise<V,X>) -> Promise<V,X>{
// return t;
//}
public class func resolve<K>(t:K) -> Promise<K,NSError>{
let p:Promise<K,NSError> = Promise<K,NSError>()
p.state.state = .Fulfilled
p.state.value = t
return p
}
private class func async(fn:() -> ()) {
dispatch_async(dispatch_get_main_queue(), {
fn()
})
}
public init(resolver:((T) -> (), reject:(E) -> ()) -> ()) {
resolver({(t:T) in
Promise.async({
self.fulfill(t)
for handler in self.fHandlers {
Promise.async({ handler(t) })
}
})
} ,
{ (e:E) in
Promise.async({
self.reject(e)
for handler in self.rHandlers {
Promise.async({ handler(e) })
}
})
})
}
private init(){
}
func then<NT,NE>(onFulfilled:(T) -> Promise<NT,NE?>) -> Promise<NT,NE?> {
var p = Promise<NT,NE?>()
switch self.state.state {
case .Rejected:
Promise.async({ p.reject(self.state.error as NE?) }) // the hell with checked exceptions
case .Fulfilled:
Promise.async({
let result = onFulfilled(self.state.value!)
result.then( { p.fulfill($0) })
result.catch( {p.reject($0) })
})
case .Pending:
fHandlers.append({ (t:T) in
let res = onFulfilled(t)
res.then({ p.fulfill($0) })
res.catch({ p.reject($0) })
})
}
return p
}
func then<NT>(onFulfilled:(T) -> NT) -> Promise<NT,E> {
var p = Promise<NT,E>()
switch self.state.state {
case .Rejected :
Promise.async({ p.reject(self.state.error!) })
case .Fulfilled :
Promise.async({
let result = onFulfilled(self.state.value!)
p.fulfill(result)
})
case .Pending :
fHandlers.append({ (t:T) in
let res = onFulfilled(t)
p.fulfill(res)
})
}
return p
}
func catch<NT,NE>(onRejected: (E?) -> Promise<NT,NE>) -> Promise<NT,NE>{
var p = Promise<NT,NE>()
switch self.state.state {
case .Pending:
rHandlers.append({ (t:E?) in
let res = onRejected(t)
res.then({ p.fulfill($0) })
res.catch({ p.reject($0) })
})
case .Fulfilled:
Promise.async({
p.fulfill(self.state.value as NT)
})
case .Rejected:
Promise.async({
let res = onRejected(self.state.error)
res.then({ p.fulfill($0) })
res.then({ p.fulfill($0) })
})
}
return p;
}
func catch<NT>(onRejected: (E?) -> NT) -> Promise<NT,E> {
var p = Promise<NT,E>()
switch self.state.state {
case .Pending:
rHandlers.append({ (t:E?) in
let res = onRejected(t)
p.fulfill(res)
})
case .Fulfilled:
Promise.async({
p.fulfill(self.state.value as NT)
})
case .Rejected:
Promise.async({
let res = onRejected(self.state.error)
p.fulfill(res)
})
}
return p
}
private func fulfill(val:T) {
if state.state != .Pending {
return
}
self.state.state = .Fulfilled
self.state.value = val
}
private func reject(err:E?) {
if state.state != .Pending {
return
}
assert(self.state.state != .Rejected)
self.state.state = .Rejected
self.state.error = err
}
}
struct PromiseState<T,E> {
var state:State
var value:T?
var error:E?
}
// hack for - unimplemented IR generation feature non-fixed multi-payload enum layout
enum State {
case Pending
case Fulfilled
case Rejected
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment