Created
August 12, 2014 18:34
-
-
Save benjamingr/21dda08002b09c930fe6 to your computer and use it in GitHub Desktop.
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
// compile error | |
Promise.resolve(15).then({ | |
print("Got2 \($0)") | |
}) | |
// works | |
Promise<Any,Any>.resolve(15).then({ | |
print("Got2 \($0)") | |
}) |
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
// | |
// 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