I will show you my implementation:

let take = { (s:String) in  
    let c = s
    print(s)
}

DispatchQueue.main.async {  
    take("first call!")
}

// To make our following code cleaner, we delcare a alias here, and thanks to swift3.0, we can now use generic type here!
typealias clr<T> = (@escaping (T?)->()) -> ()

/// What when do, is to take a type, bootstrap a chain
func when<T>(type:T.Type,f: @escaping clr<T> ) -> clr<T> {  
    let q:(@escaping (T?)->())->() = { (done: @escaping (T?) -> ()) in
        f({ (signal) in
            done(signal)
        })
    }
    return q
}

/// A convenience operator of when<T>
infix operator ??? { percendence 140 }  
func ??? <T>(type:T.Type, f: @escaping clr<T>) -> clr<T> {  
    let q:(@escaping (T?)->())->() = { (done: @escaping (T?) -> ()) in
        f({ (signal) in
            done(signal)
        })
    }
    return q
}

/// Stick more handling chain with previous
infix operator <== { percendence 120 }  
func <== <T,U>(l: @escaping clr<T>, r: @escaping ((T?)->clr<U>)) -> clr<U> {  
    return { g in
        l({ (a) in
            let v = r(a)
            v({ (ok) in
                g(ok)
            })
        })
    }
}

/// The final operation of a promise block, we treat a nil return as a fail
infix operator ==> { percendence 100 }  
func ==> <T,U> (task: @escaping clr<T>, done: (ok:((T)->U), fail: ()->U)) {  
    return task({ (ok) in
        if let ok = ok {
            done.ok(ok)
        }else{
            done.fail()
        }
    })

}

Now let's look at the results!
 
 
Original post from my previous site: http://povoq.blogspot.com/2017/07/promise-in-swift-part-2.html