Skip to content

Instantly share code, notes, and snippets.

@paulofaria
Last active March 18, 2016 17:11
Show Gist options
  • Save paulofaria/1aa155987f5f1f905081 to your computer and use it in GitHub Desktop.
Save paulofaria/1aa155987f5f1f905081 to your computer and use it in GitHub Desktop.
import Dispatch
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
func delay(duration: Double, closure: Void -> Void) {
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(duration * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue(), closure)
}
func testResponder(responder: AsyncResponder) {
responder.respond(Request(body: "Foo")) { result in
do {
let response = try result()
print(response)
} catch {
print(error)
}
}
}
// Request/Response
struct Request {
let body: String
}
struct Response {
let body: String
}
// Sync Responder
protocol Responder: AsyncResponder {
func respond(request: Request) throws -> Response
}
extension Responder {
func respond(request: Request, asyncResponse: AsyncResponse) {
asyncResponse {
try self.respond(request)
}
}
}
// Async Responder
typealias AsyncResponse = (Void throws -> Response) -> Void
protocol AsyncResponder {
func respond(request: Request, asyncResponse: AsyncResponse)
}
// Result Responder
enum Result<T> {
case Success(T)
case Failure(ErrorType)
}
typealias ResultResponse = Result<Response> -> Void
protocol ResultResponder: AsyncResponder {
func respond(request: Request, resultResponse: ResultResponse)
}
extension ResultResponder {
func respond(request: Request, asyncResponse: AsyncResponse) {
self.respond(request) { result in
switch result {
case .Success(let response):
asyncResponse {
response
}
case .Failure(let error):
asyncResponse {
throw error
}
}
}
}
}
// Future Responder
final class Future<T> {
typealias Completion = Result<T> -> Void
typealias Success = T -> Void
typealias Failure = ErrorType -> Void
var completion: Completion?
var success: Success?
var failure: Failure?
var result: Result<T>?
init(future: Future<T> -> Void) {
future(self)
}
func succeed(value: T) {
result = Result.Success(value)
success?(value)
}
func onSuccess(success: Success) -> Future<T> {
if let result = result {
if case .Success(let value) = result {
success(value)
}
} else {
self.success = success
}
return self
}
func fail(error: ErrorType) {
result = Result.Failure(error)
failure?(error)
}
func onFailure(failure: Failure) -> Future<T> {
if let result = result {
if case .Failure(let error) = result {
failure(error)
}
} else {
self.failure = failure
}
return self
}
func complete(result: Result<T>) {
self.result = result
switch result {
case .Success(let value):
succeed(value)
case .Failure(let error):
fail(error)
}
complete(result)
}
func onCompletion(completion: Completion) -> Future<T> {
if let result = result {
completion(result)
} else {
self.completion = completion
}
return self
}
}
protocol FutureResponder: AsyncResponder {
func respond(request: Request) -> Future<Response>
}
extension FutureResponder {
func respond(request: Request, asyncResponse: AsyncResponse) {
self.respond(request)
.onSuccess { response in
asyncResponse {
response
}
}.onFailure { error in
asyncResponse {
throw error
}
}
}
}
// Responder Usage
struct ResponderExample: Responder {
func respond(request: Request) -> Response {
return Response(body: request.body)
}
}
testResponder(ResponderExample())
// AsyncResponder Usage
struct AsyncResponderExample: AsyncResponder {
func respond(request: Request, asyncResponse: AsyncResponse) {
delay(1) {
asyncResponse {
Response(body: request.body + " Async")
}
}
}
}
testResponder(AsyncResponderExample())
// ResultResponder Usage
struct ResultResponderExample: ResultResponder {
func respond(request: Request, resultResponse: ResultResponse) {
delay(2) {
let response = Response(body: request.body + " Result")
resultResponse(Result.Success(response))
}
}
}
testResponder(ResultResponderExample())
// FutureResponder Usage
struct FutureResponderExample: FutureResponder {
func respond(request: Request) -> Future<Response> {
return Future<Response> { future in
delay(3) {
let response = Response(body: request.body + " Future")
future.succeed(response)
}
}
}
}
testResponder(FutureResponderExample())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment