Here I would like to implement 'Promise' like blocks. But I'm not able to set the result for the blocks.
Here I have 2 Challenges :
How can I achieve multiple times?
Here is my example.
class Promise<T> {
private var resultHandler : ((_ result:T)->())?
private var errorHandler : ((_ error:String)->())?
private var final : (()->())?
func resolve(_ value: T) {
resultHandler?(value)
final?()
}
func reject(_ value: String) {
errorHandler?(value)
final?()
}
func then(_ block:@escaping (_ result:T)->()) {
resultHandler = block
}
func error(_ block:@escaping (_ result:String)->()) {
errorHandler = block
}
func finally(_ block:@escaping ()->()) {
final = block
}
}
func getFullName(firstname: String, lastname: String) -> Promise<String> {
let p = Promise<String>()
if firstname.count > 0 && lastname.count > 0 {
let name = firstname + " " + lastname
p.resolve(name)
}
else {
print("--")
p.reject("Firstname and Lastname can't be empty" )
}
return p
}
let p = getFullName(firstname: "Alen", lastname: "Stel")
p.then { (name) in
print("Name", name)
}
First, to chain things like then
, you need to chain the handlers, for example:
func then(block: @escaping (T)->()) {
if let oldHandler = resultHandler {
resultHandler = {
oldHandler($0)
block($0)
}
} else {
resultHandler = block
}
}
Or you can simplify things by making resultHandler
non-optional:
private var resultHandler: (T)->() = {}
...
func then(block: @escaping (T)->()) {
resultHandler = { [oldHandler] in
oldHandler($0)
block($0)
}
}
You can do similar things to error
and finally
if you like.
To your existing code, you're attaching then
after the Promise is resolved. You have to manage that case. You can do that with a enum State
(like .pending
, .resolved
, .error
) or just using some variables like:
private var value: T?
...
func then(block: @escaping (T)->()) {
if let value = value {
block(value)
} else {
resultHandler = { [oldHandler] in
oldHandler($0)
block($0)
}
}
func resolve(_ value: T) {
self.value = value
resultHandler(value)
resultHandler = {}
final()
final = {}
}
(Or something along those lines. I haven't completely tested this.)
Keep in mind that this is all thread-unsafe, so you have to be careful about adding .then
clauses or resolving on different queues, but that can be fine in a simple Promise type as long as you keep that in mind (and makes it dramatically simpler....)