Created
February 14, 2019 15:07
-
-
Save ashikahmad/0661f38bd3f78c35bcf829ce9b6f3b4b 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
import UIKit | |
import PlaygroundSupport | |
extension String: Error {} | |
func getEvenNumber() -> Future<Int> { | |
return Future<Int>.create { p in | |
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { | |
let num = Int.random(in: 0...20) | |
if num % 2 == 0 { | |
p.fulfill(with: num) | |
} else { | |
p.reject(with: "\(num) - Not Even") | |
} | |
} | |
} | |
} | |
// ----[ USAGE ]------------------------ | |
PlaygroundPage.current.needsIndefiniteExecution = true | |
getEvenNumber() | |
.chain { num -> Future<String> in | |
return Future<String>.create { p in | |
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: { | |
p.fulfill(with: "-- \(num) --") | |
}) | |
} | |
}.map { str -> Int in | |
print(str) | |
let num = str.count | |
if num == 8 { throw "Two Digit" } | |
return num | |
}.onCompletion { val in | |
print("Value:", val) | |
}.onError { err in | |
print("Error:", err) | |
}.finally { | |
print("Finish!") | |
} | |
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 | |
* ----------------------------------------------------------- | |
* Project : Promise (Playground) | |
* Created on : 14 Feb, 2019 | |
* Created by : Ashik uddin Ahmad (ashik.u.ahmad@gmail.com) | |
* ----------------------------------------------------------- | |
* Copyright © 2018 Ashik uddin Ahmad. All rights reserved. | |
*/ | |
import Foundation | |
// ----------------------------------------------------------- | |
// MARK: - Result | |
// ----------------------------------------------------------- | |
fileprivate enum Result<V> { | |
case success(V) | |
case failure(Error) | |
} | |
// ----------------------------------------------------------- | |
// MARK: - Future | |
// ----------------------------------------------------------- | |
public class Future<V> { | |
fileprivate var _result: Result<V>? { | |
didSet { broadcast() } | |
} | |
private lazy var completions: [((Result<V>)->Void)] = [] | |
private func broadcast() { | |
if let r = _result { | |
for completion in completions { | |
completion(r) | |
} | |
} | |
} | |
fileprivate func observe(_ closure: @escaping (Result<V>)->Void) { | |
completions.append(closure) | |
if let r = _result { | |
closure(r) | |
} | |
} | |
} | |
// ----------------------------------------------------------- | |
// MARK: - Promise | |
// ----------------------------------------------------------- | |
public class Promise<V>: Future<V> { | |
public func fulfill(with value: V) { | |
_result = .success(value) | |
} | |
public func reject(with error: Error) { | |
_result = .failure(error) | |
} | |
} | |
// ----------------------------------------------------------- | |
// MARK: - Future - Observing | |
// ----------------------------------------------------------- | |
public extension Future { | |
public func onCompletion(_ closure: @escaping (V)->Void) -> Future<V> { | |
observe { result in | |
if case let .success(val) = result { | |
closure(val) | |
} | |
} | |
return self | |
} | |
public func onError(_ closure: @escaping (Error)->Void) -> Future<V> { | |
observe { result in | |
if case let .failure(err) = result { | |
closure(err) | |
} | |
} | |
return self | |
} | |
public func finally(_ closure: @escaping ()->Void) { | |
observe { _ in | |
closure() | |
} | |
} | |
} | |
// ----------------------------------------------------------- | |
// MARK: - Future - Building | |
// ----------------------------------------------------------- | |
public extension Future { | |
public static func create(_ builder: (Promise<V>)->Void)->Future<V> { | |
let p = Promise<V>() | |
builder(p) | |
return p | |
} | |
} | |
// ----------------------------------------------------------- | |
// MARK: - Future - Chaining & Transformation | |
// ----------------------------------------------------------- | |
public extension Future { | |
public func chain<U>(_ transform: @escaping (V) throws ->Future<U>)->Future<U> { | |
return Future<U>.create { p in | |
self.observe { result in | |
switch result { | |
case .success(let val): | |
do { | |
let p2 = try transform(val) | |
p2.observe { r in | |
switch r { | |
case .success(let v): | |
p.fulfill(with: v) | |
case .failure(let e): | |
p.reject(with: e) | |
} | |
} | |
} catch { | |
p.reject(with: error) | |
} | |
case .failure(let err): | |
p.reject(with: err) | |
} | |
} | |
} | |
} | |
public func map<U>(_ transform: @escaping (V) throws ->U)->Future<U> { | |
return Future<U>.create { p in | |
self.observe { result in | |
switch result { | |
case .success(let val): | |
do { | |
let v2 = try transform(val) | |
p.fulfill(with: v2) | |
} catch { | |
p.reject(with: error) | |
} | |
case .failure(let err): | |
p.reject(with: err) | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment