churabou / iOS-develop-blog

0 stars 0 forks source link

swiftでpromise #38

Open churabou opened 6 years ago

churabou commented 6 years ago

enum State {
    case pending
    case resolve
    case reject
}

enum Result<T> {
    case undefined
    case value(T)
    case error(Swift.Error)
}

public final class Promise<T> {

    private(set) var state: State = .pending {
        didSet {
            if case .pending = oldValue {
                switch (state, result) {
                case (.resolve, .value(let value)):
                    resolve?(value)
                case (.reject, .error(let error)):
                    reject?(error)
                default: break
                }
            }
        }
    }

    private var resolve: ((T) -> Void)?
    private var reject: ((Swift.Error) -> Void)?

    internal private(set) var result: Result<T> = .undefined

    public init(_ executor: @escaping ((T) -> Swift.Void, (Swift.Error) -> Swift.Void) -> Swift.Void) {

        DispatchQueue.main.async {
            executor(self.resolved, self.rejected)
        }
    }

    // stateとresultを更新する
    private func resolved(value: T) {
        if case .pending = state {
            result = .value(value)
            state = .resolve
        }
    }

    // stateとresultを更新する
    private func rejected(error: Swift.Error) {
        if case .pending = state {
            result = .error(error)
            state = .reject
        }
    }
}

enum State {
    case pending
    case fulfilled
    case rejected
    case resolved
}

enum Result<T> {
    case undefined
    case value(T)
    case error(Error)
}

class Promise<T> {

    private (set) var state: State = .pending {

        didSet {
            // then
            if case .pending = oldValue {
                switch (state, result) {
                case (.fulfilled, .value(let value)):
                    resolve?(value)
                case (.rejected, .error(let error)):
                    reject?(error)
                default: break
                }
            }
        }
    }

    private var resolve: FullfillClosure?
    private var reject: RejectClosure?

    func then<U>(onFulfilled: @escaping (T) -> U, _ onRejected: ((Error) -> Void)?) -> Promise<U> {
        return Promise<U> { resolve, _reject in
            switch (self.state, self.result) {
            case (.pending, _):
                self.resolve = { (value: T) in
                    _resolve(onFulfilled(value))
                }
//                let resolve = self.resolve
//                self.resolve = {
//                    resolve?($0)
//                    _resolve(onFulfilled($0))
//                }
            default: break
            }
        }
    }
    private var result: Result<T> = .undefined

    typealias FullfillClosure =  (T) -> Swift.Void
    typealias RejectClosure = (Error) -> Swift.Void

    public init(_ executor: @escaping (FullfillClosure, RejectClosure) -> Swift.Void) {
        DispatchQueue.main.async {
            executor(self.onFullfilled, self.onRejected)
        }
    }

    func onFullfilled(value: T) {
        if case .fulfilled = state {
            result = .value(value)
            state = .fulfilled
        }
    }

    private func onRejected(error: Error) {
        if case .pending = state {
            result = .error(error)
            state = .rejected
        }
    }
}

let taskA = Promise<Int> { fullfill , error in

}