在这里,我想实现'承诺'像块。但我无法设置块的结果。
这里我有两个挑战:
我正在尝试实现一个简单的Promise示例
来自名字和姓氏的字符串。
我想多次打电话给“then”。
首先我想从两个网站上都查到全名。
然后转换成大写。
然后转换成小写。
……等等(意思是说在一些任务中有多个“then”条件。)
我怎样才能做到多次?
这是我的例子。
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)
}
最佳答案
首先,要链接then
,需要链接处理程序,例如:
func then(block: @escaping (T)->()) {
if let oldHandler = resultHandler {
resultHandler = {
oldHandler($0)
block($0)
}
} else {
resultHandler = block
}
}
或者您可以通过将
resultHandler
设为非可选来简化:private var resultHandler: (T)->() = {}
...
func then(block: @escaping (T)->()) {
resultHandler = { [oldHandler] in
oldHandler($0)
block($0)
}
}
如果您愿意,可以对
error
和finally
执行类似的操作。对于您现有的代码,在解决了承诺之后,您附加了
then
。你必须处理这个案子。可以使用枚举(如State
,.pending
,.resolved
,.error
)或仅使用一些变量(如: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 = {}
}
(或者类似的东西。我还没有完全测试过。)
请记住,这都是线程不安全的,所以在添加
.then
子句或在不同的队列上解析时必须小心,但在简单的Promise类型中,只要记住这一点(并使其显著简化……)就可以了