［Swift］PromiseKit を利用した非同期処理

### 書くこと
Promise を利用した非同期処理
※忘れた時に確認するための備忘録

### 開発環境

<table>
<tr><td>PC</td><td>MacBook Air（13-inch,2017）</td><tr>
<tr><td>PC OS</td><td>macOS Catalina（ver 10.15.6）</td><tr>
<tr><td>IDE</td><td>Xcode（ver 12.0.1）</td><tr>
<tr><td>iPhone</td><td>SE（2nd Generation）</td><tr>
<tr><td>iPhone OS</td><td>ver 14.0.1</td><tr>
<tr><td>Swift</td><td>5.3</td><tr>
</table>

### 前提条件
① MacBook Air と iPhone は USBケーブルで接続する
② Xcode を利用してデスクトップ上に `Sample` というプロジェクトアプリを作成する
③ `Sample` は既に `CocoaPods` 利用して `PromiseKit` を導入している状態である
④ 今回は、 `Sample` にある `ViewController.swift` にコードを記述する

### 基本的なコード
```swift:ViewController.swift
import UIKit
import PromiseKit

class ViewController: UIViewController {

        override func viewDidLoad() {

            let promise = Promise<String> { value in
                // 処理
            }.done { value in
                // 成功した時に実行
            }.catch { error in
                // 失敗した時に実行
            }.finally {
                // 最後に実行
            }
        }
    
}
```

### コード例①
```swift:ViewController.swift
import UIKit
import PromiseKit

class ViewController: UIViewController {

        override func viewDidLoad() {
            print("----- promise ここから -----")
            
            let promise = Promise<String> { value in
                // 処理
                DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
                    value.fulfill("sample1")
                    print("\(Date()) [1]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 4.0) {
                    value.fulfill("sample2")
                    print("\(Date()) [2]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
                    value.fulfill("sample3")
                    print("\(Date()) [3]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                    value.fulfill("sample4")
                    print("\(Date()) [4]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                    value.fulfill("sample5")
                    print("\(Date()) [5]：\(value)")
                }
                print("\(Date()) [6]：\(value)")
            }.done { value in
                // 成功した時に実行
                print("\(Date()) [7]：\(value)")
            }.catch { error in
                // 失敗した時に実行
                print("\(Date()) [8]：\(error.localizedDescription)")
            }.finally {
                // 最後に実行
                print("\(Date()) [9]：処理を終了します")
            }
            print("----- promise ここまで -----")
        }
    
}
```

### コード例① 実行結果
```txt:Xcodeログ
----- promise ここから -----
2020-10-22 13:16:28 +0000 [6]：PromiseKit.Resolver<Swift.String>
----- promise ここまで -----
2020-10-22 13:16:29 +0000 [5]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:16:29 +0000 [7]：sample5
2020-10-22 13:16:29 +0000 [9]：処理を終了します
2020-10-22 13:16:30 +0000 [4]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:16:31 +0000 [3]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:16:32 +0000 [2]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:16:33 +0000 [1]：PromiseKit.Resolver<Swift.String>
```

### コード例②
```swift:ViewController.swift
import UIKit
import PromiseKit

enum SampleError: Error {
    case error1
    case error2
    case error3
}

class ViewController: UIViewController {

        override func viewDidLoad() {
            print("----- promise ここから -----")
            
            let promise = Promise<String> { value in
                // 処理
                value.reject(SampleError.error1)
                
                DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
                    value.fulfill("sample1")
                    print("\(Date()) [1]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 4.0) {
                    value.fulfill("sample2")
                    print("\(Date()) [2]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
                    value.fulfill("sample3")
                    print("\(Date()) [3]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                    value.fulfill("sample4")
                    print("\(Date()) [4]：\(value)")
                }
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                    value.fulfill("sample5")
                    print("\(Date()) [5]：\(value)")
                }
                print("\(Date()) [6]：\(value)")
            }.done { value in
                // 成功した時に実行
                print("\(Date()) [7]：\(value)")
            }.catch { error in
                // 失敗した時に実行
                print("\(Date()) [8]：\(error.localizedDescription)")
            }.finally {
                // 最後に実行
                print("\(Date()) [9]：処理を終了します")
            }
            print("----- promise ここまで -----")
        }
    
}
```

### コード例② 実行結果
```txt:Xcodeログ
----- promise ここから -----
2020-10-22 13:26:04 +0000 [6]：PromiseKit.Resolver<Swift.String>
----- promise ここまで -----
2020-10-22 13:26:04 +0000 [8]：The operation couldn’t be completed. (Sample.SampleError error 0.)
2020-10-22 13:26:04 +0000 [9]：処理を終了します
2020-10-22 13:26:05 +0000 [5]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:26:06 +0000 [4]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:26:07 +0000 [3]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:26:08 +0000 [2]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:26:09 +0000 [1]：PromiseKit.Resolver<Swift.String>
```

### コード例③
```swift:ViewController.swift
import UIKit
import PromiseKit

enum SampleError: Error {
    case error1
    case error2
    case error3
}

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        print("----- promise ここから -----")
        
        let promise = Promise<String> { value in
            // 処理
            value.fulfill("sample1")
            print("\(Date()) [1]：\(value)")
            
            value.fulfill("sample2")
            print("\(Date()) [2]：\(value)")
            
            value.fulfill("sample3")
            print("\(Date()) [3]：\(value)")
            
            value.fulfill("sample4")
            print("\(Date()) [4]：\(value)")
            
            value.fulfill("sample5")
            print("\(Date()) [5]：\(value)")
            
            print("\(Date()) [6]：\(value)")
        }.done { value in
            // 成功した時に実行
            print("\(Date()) [7]：\(value)")
        }.catch { error in
            // 失敗した時に実行
            print("\(Date()) [8]：\(error.localizedDescription)")
        }.finally {
            // 最後に実行
            print("\(Date()) [9]：処理を終了します")
        }
        print("----- promise ここまで -----")
    }
    
}
```

### コード例③ 実行結果
```txt:Xcodeログ
----- promise ここから -----
2020-10-22 13:29:03 +0000 [1]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:29:03 +0000 [2]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:29:03 +0000 [3]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:29:03 +0000 [4]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:29:03 +0000 [5]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:29:03 +0000 [6]：PromiseKit.Resolver<Swift.String>
----- promise ここまで -----
2020-10-22 13:29:03 +0000 [7]：sample1
2020-10-22 13:29:03 +0000 [9]：処理を終了します
```

### コード例④
```swift:ViewController.swift
import UIKit
import PromiseKit

enum SampleError: Error {
    case error1
    case error2
    case error3
}

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        print("----- promise ここから -----")
        
        let promise = Promise<String> { value in
            // 処理
            value.reject(SampleError.error1)
            
            value.fulfill("sample1")
            print("\(Date()) [1]：\(value)")
            
            value.fulfill("sample2")
            print("\(Date()) [2]：\(value)")
            
            value.fulfill("sample3")
            print("\(Date()) [3]：\(value)")
            
            value.fulfill("sample4")
            print("\(Date()) [4]：\(value)")
            
            value.fulfill("sample5")
            print("\(Date()) [5]：\(value)")
            
            print("\(Date()) [6]：\(value)")
        }.done { value in
            // 成功した時に実行
            print("\(Date()) [7]：\(value)")
        }.catch { error in
            // 失敗した時に実行
            print("\(Date()) [8]：\(error.localizedDescription)")
        }.finally {
            // 最後に実行
            print("\(Date()) [9]：処理を終了します")
        }
        print("----- promise ここまで -----")
    }
    
}
```

### コード例④ 出力結果
```txt:Xcodeログ
----- promise ここから -----
2020-10-22 13:33:08 +0000 [1]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:33:08 +0000 [2]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:33:08 +0000 [3]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:33:08 +0000 [4]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:33:08 +0000 [5]：PromiseKit.Resolver<Swift.String>
2020-10-22 13:33:08 +0000 [6]：PromiseKit.Resolver<Swift.String>
----- promise ここまで -----
2020-10-22 13:33:08 +0000 [8]：The operation couldn’t be completed. (Sample.SampleError error 0.)
2020-10-22 13:33:08 +0000 [9]：処理を終了します

```