PromisePatternをSwiftで実装してみた

デザインパターンをSwiftで書いてみます。
今回は、Promiseパターンを実装してみます。

## description

　　[定義]  (非同期処理も) 同期的に順番に実行する
　　　
　　[用例]  2つのAPIを決めた順序で呼べる (始めの結果を 次の引数に使う とか)
　　　　
　　[備考]  順番を保証することからPromiseと呼ばれるようになったとか
　　　　　　.then().then()と関数でチェーンする この順番の保証が
　　　　　　Promiseの由来と思われる


## sample code

例えば、通信周りで 非同期のWebAPIを連続して呼びたい時

なるべくシンプルな作りになるように意識してみましたので、
各フィードバック(成功時、失敗時)は、自分で記載しないと動きません。
ゆえにシンプル、ゆえに予想外の動きは起きにくい、、、かな

```swift:ViewController_or_Presenter_and_so_on

// MARK: - ApiFetch
extension SomethinghViewController: ApiFetch {
    
    func fetch() {

        let deferred = Deferred()
            deferred.then { (obj) in
                self.presenter.fetch({ (result) in
                    switch result {
                    case .success(let value): deferred.resolve(value)
                    case .failure(let error): deferred.reject(error)
                    }
                })
            }
            .then{ (obj) in
                self.presenter.fetchAnother{ (result) in
                    switch result {
                    case .success(let value): deferred.resolve(value)
                    case .failure(let error): deferred.reject(error)
                    }
                }
            }
            .fail { (err) in
                if let error = err as? NSError {
                    self.fetchFailed(error)
                }
                deferred.finish()
            }
            .finally { (_) in
                self.fetched()
            }
            .fire()
    }
    
    func fetchFailed(_ error: NSError) {
        // write if need
    }
    
    func fetchSucceeded() {
        // write if need
    }
    
    func fetched() {
        // write if need
    }

}

```

ついでですが、protocolでコールバックで呼ばれるメソッドを定義しておくと
各使用箇所で統一されていいよね。(プロトコル指向を意識！)

```swift:ApiFetch
protocol ApiFetch {

    func fetch()

    func fetchFailed(_ error: NSError)

    func fetchSucceeded()

    func fetched()
    
}
```

Promiseパターンを実装したDeferredクラスはこちら
いろんな方がこのパターンを実装していますので大分参考にさせて頂きました。

```swift:Deferred.swift
class Deferred: NSObject {

    // MARK: - properties
    enum State: Int{
        case unresolved
        case resolved
        case rejected
    }
    fileprivate var state: State = .unresolved
    fileprivate var resolvedTasks:  Array<(Any?)->Void> = []
    fileprivate var failedTasks:    Array<(Any?)->Void> = []  // rejecteds
    fileprivate var finallyTasks:   Array<(Any?)->Void> = []
    fileprivate var responseObject: Any? = nil

    
    // MARK: - public
    /// stack
    /// Feedback is necessary to advance the task.
    func then(_ callBack: @escaping (Any)->Void) -> Deferred {
        resolvedTasks.append(callBack)
        return self
    }
    /// stack
    /// Feedback is necessary to advance the task.
    func fail(_ callBack: @escaping (Any)->Void) -> Deferred {
        failedTasks.append(callBack)
        return self
    }
    /// stack
    func finally(_ callBack: @escaping (Any)->Void) -> Deferred {
        finallyTasks.append(callBack)
        return self
    }
    /// trigger
    func fire() {
        switch state {
        case .unresolved:
            self.switchResolved()
            self.excute()
        case .resolved, .rejected:
            break // Do nothing
        }
    }
    /// feedback
    func resolve(_ response: Any? = nil){
        switch state {
        case .unresolved, .resolved:
            self.switchResolved()
            self.responseObject = response
            self.excute()
        case .rejected:
            break // Do nothing
        }
    }
    /// feedback
    func reject(_ response: Any? = nil){
        // do any state
        self.switchRejected()
        self.responseObject = response
        self.excute()
    }
    /// feedback
    func finish(){
        self.excute()
    }
    
}



// MARK: - private
extension Deferred {

    fileprivate func excute() {
        switch state {
        case .unresolved, .resolved:
            self.executeResolveTask()
        case .rejected:
            self.execureFailureTask()
        }
    }
    
    fileprivate func switchResolved() {
        state = .resolved
    }
    
    fileprivate func switchRejected() {
        state = .rejected
    }
    
    fileprivate func executeResolveTask() {
        if let first = resolvedTasks.first {
            resolvedTasks.removeFirst(1)
            let response = self.responseObject ?? nil
            self.responseObject = nil
            first(response)
        }
        else if let final = finallyTasks.first {
            finallyTasks.removeFirst(1)
            final(nil)
        }
    }
    
    fileprivate func execureFailureTask() {
        if let first = failedTasks.first {
            failedTasks.removeFirst(1)
            let response = self.responseObject ?? nil
            self.responseObject = nil
            first(response)
        }
        else if let final = finallyTasks.first {
            finallyTasks.removeFirst(1)
            final(nil)
        }
    }

}
```

## Impressions

使ってみて、結構非同期処理など安心安定した感があります。
実装がパターン化できて、アーキテクチャーとして纏まり、
一貫性のあるコードになってきた気がします。(イイですね。)


世の中的にPromiseパターンはしっかり使われていることに気がつきました。
・RxSwiftのストリーム
・ReactorKit(RxSwift)
　...RxSwiftのストリームって、要はPromiseだったんだ、、


Webの世界でも使われているんですね
・ECMAScript6.0(?)のPromiseメソッド
・(↑JSでPromiseということは、)node.js

APIと連携など非同期の連続処理が、
きっとどのプラットフォームでも必要なんですね。
みなさんは、こういう時どうしているのでしょうか？



今回のコードはこちらになります。
https://github.com/YuuichiWatanabe/SimpleDeferred