Skip to content

liuyx7894/SimplePromiseImplement

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

SimplePromiseImplement

A very simple promise implement



import UIKit

typealias PromiseHandler = (Resolve, Reject)->Void
typealias Resolve = (Any?)throws ->Any?
typealias Reject = (Error?)->Any?
typealias Callback = ()->Void

enum PromiseState:Int{
    case pending = 0
    case resolve = 1
    case reject  = 2
}
struct PromiseError: Error {
}
func delay(_ second:Double, closure:@escaping ()->()) {
    DispatchQueue.main.asyncAfter(
        deadline: DispatchTime.now() + Double(Int64(second * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
}

class Promise{
    
    var state:PromiseState = .pending
    var value:Any?
    var error:Error?
    var resolveCallbackList = [Callback]()
    var rejectCallbackList = [Callback]()
    var doneCallbackList = [Callback]()
    
    init() {
        
    }
    init(value:Any) {
        fill(value)
    }
    init(callback:@escaping ((@escaping Resolve,@escaping Reject) throws ->Void)) {
        DispatchQueue.main.async {
            do {
                try callback(self.resolve, self.reject)
            } catch {
                self.reject(nil)
            }
        }
    }
    
    func resolve(_ data:Any?) -> Void {
        guard state == .pending else { return }
        value = data
        state = .resolve
        resolveCallbackList.forEach { $0() }
    }
    
    func reject(_ e:Error?) -> Void {
        guard state == .pending else { return }
        error = e
        state = .reject
        rejectCallbackList.forEach { $0() }
    }
    
    func fill(_ data:Any?){
        guard state == .pending else { return }
        value = data
        state = .resolve
    }
    
    func resolvePromise(promise2:Promise, x:Any?, resolve: Resolve?, reject: Reject?)throws {
  
        if let p = x as? Promise{
//            guard p != promise2 else {
//                reject(PromiseError())
//                return
//            }
            
            p.then({ (data) in
                if let p2  = data as? Promise{
                    do {
                        try self.resolvePromise(promise2: promise2, x: p2, resolve: resolve, reject: reject)
                    } catch {
                        reject?(error)
                    }
                    return nil
                }else{
                    do {
                        try resolve?(data)
                    } catch {
                        reject?(error)
                    }
                    return nil
                }
            }, { error in
                reject?(error)
            })
        }else{
            do {
                try resolve?(value)
            } catch {
                reject?(error)
            }
        }
    }
}

extension Promise{
    
    func then(_ onFulfilled:@escaping Resolve) -> Promise {
        return Promise { (resolve, reject) in
            self.resolveCallbackList.append({
                DispatchQueue.main.async {
                    do {
                        try onFulfilled(self.value)
                        self.then(resolve, reject)
                    } catch {
                        reject(error)
                    }
                }
            })
        }
    }
    
    func then(_  onFulfilled: Resolve?, _ onRejected: Reject?) ->Promise{
        var promise2:Promise!
        promise2 = Promise{ (resolve, reject) in
            
            switch self.state {
            case .resolve:
                DispatchQueue.main.async {
                    do {
                        let x = try onFulfilled?(self.value)
                        try self.resolvePromise(promise2: promise2, x: x, resolve: resolve, reject: reject)
                    } catch {
                        reject(error)
                    }
                }
                
            case .reject:
                DispatchQueue.main.async {
                    do {
                        print("reject \(self.value)")
                        let x = onRejected?(self.error)
                        try self.resolvePromise(promise2: promise2, x: x, resolve: resolve, reject: reject)
                    } catch {
                        reject(error)
                    }
                }
            case .pending:
                self.resolveCallbackList.append({
                    DispatchQueue.main.async {
                        do {
                            let x = try onFulfilled?(self.value)
                            try self.resolvePromise(promise2: promise2, x: x, resolve: resolve, reject: reject)
                        } catch {
                            reject(error)
                        }
                    }
                })
                
                self.rejectCallbackList.append({
                    
                    DispatchQueue.main.async {
                        do {
                            let x = onRejected?(self.error)
                            try self.resolvePromise(promise2: promise2, x: x, resolve: resolve, reject: reject)
                        } catch {
                            reject(error)
                        }
                    }
                })
            }
        }
        return promise2
    }
    
    func onFail(_ reject:Reject?) -> Promise{
        return self.then(nil, reject)
    }
    
    func done(_ resolve:Resolve?) -> Promise{
        return self.then(resolve, nil)
    }
}

About

A very simple promise implement

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published