Swift 如何在结果中返回.map函数中的失败
我有一个方法Swift 如何在结果中返回.map函数中的失败,swift,Swift,我有一个方法execute,它通过一个接收Result的回调调用一个外部API。如何将可选的成功映射到未包装的结果或错误 func execute(then handle: @escaping (Result<Data, Error>) -> Void) { externalAPI.retrieveData { result in let mappedResult = result .map { g
execute
,它通过一个接收Result
的回调调用一个外部API。如何将可选的成功映射到未包装的结果或错误
func execute(then handle: @escaping (Result<Data, Error>) -> Void) {
externalAPI.retrieveData { result in
let mappedResult = result
.map {
guard let data = $0 else {
throw NSError(domain: "", code: 0, description: "error")
}
return data
}
handle(mappedResult)
}
}
func执行(然后句柄:@escaping(Result)->Void){
externalAPI.retrieveData{结果为
设mappedResult=result
.地图{
guard let数据=$0其他{
抛出N错误(域:“”,代码:0,说明:“错误”)
}
返回数据
}
句柄(mappedResult)
}
}
此代码失败,从类型为“(可选)throws->”的抛出函数到类型为“(数据?)->NewSuccess”的非抛出函数的转换无效。
我可以通过一个简单的开关(如下所示)来实现这一点,但我想知道是否可以在.map中抛出一个失败
func execute(then handle: @escaping (Result<Data, Error>) -> Void) {
externalAPI.retrieveData { result in
switch result {
case .failure(let error):
handle(.failure(error))
case .success(let data):
guard let data = data else {
handle(.failure(NSError(domain: "", code: 0, description: "error")))
return
}
handle(.success(data))
}
}
}
func执行(然后句柄:@escaping(Result)->Void){
externalAPI.retrieveData{结果为
切换结果{
案例。失败(let错误):
句柄(.failure(error))
案例.成功(让数据):
guard let data=其他数据{
句柄(.failure(n错误(域:“”,代码:0,说明:“错误”))
返回
}
句柄(.success(数据))
}
}
}
显然,这可以使用。就我而言:
func execute(then handle: @escaping (Result<Data, Error>) -> Void) {
externalAPI.retrieveData { result in
let mappedResult = result
.flatMap { data in
Result<Data, Error> {
guard let data = data else {
throw NSError(domain: "", code: 0, description: "error")
}
return data
}
}
handle(mappedResult)
}
}
func执行(然后句柄:@escaping(Result)->Void){
externalAPI.retrieveData{结果为
设mappedResult=result
.flatMap{中的数据
结果{
guard let data=其他数据{
抛出N错误(域:“”,代码:0,说明:“错误”)
}
返回数据
}
}
句柄(mappedResult)
}
}
这有点让人困惑,但对我来说是可行的。您可以使用
Result(catching:)
和get()
在抛出的函数和返回结果的函数之间进行转换
这是您的原始地图
通话:
.map {
guard let data = $0 else {
throw NSError(domain: "", code: 0, description: "error")
}
return data
}
Result.map
获取一个结果和一个函数,该函数转换(Success)->NewSuccess
,并返回一个结果
您的映射获取数据
(成功),并返回结果
(NewSuccess)。因此,插入NewSuccess的最后一种类型是:Result
。这比你想要的要多。您希望将其展平为结果
,这就是flatMap
的作用所在
您的答案表明了这一点,但您也可以将其拉入一个更通用的工具中。它只在Failure==Error
时起作用,因为throws
是非类型化的,所以不能将其限制为某些错误子集。但不管怎样,这就是你正在做的。下面是tryMap
:
extension Result where Failure == Error {
func tryMap<NewSuccess>(_ transform: (Success) throws -> NewSuccess) -> Result<NewSuccess, Error> {
self.flatMap { value in
Result<NewSuccess, Error> { try transform(value) }
}
}
}
扩展结果,其中失败==错误{
func tryMap(uTransform:(Success)抛出->新闻成功)->结果{
self.flatMap{中的值
结果{尝试转换(值)}
}
}
}
这样,您可以将其改写为:
func execute(then handle: @escaping (Result<Data, Error>) -> Void) {
externalAPI.retrieveData { result in
handle(result
.tryMap {
guard let data = $0 else {
throw NSError(domain: "", code: 0, description: "error")
}
return data
})
}
}
func执行(然后句柄:@escaping(Result)->Void){
externalAPI.retrieveData{结果为
处理(结果)
.tryMap{
guard let数据=$0其他{
抛出N错误(域:“”,代码:0,说明:“错误”)
}
返回数据
})
}
}
也就是说,我可能会这么写:
func execute(then handle: @escaping (Result<Data, Error>) -> Void) {
externalAPI.retrieveData { result in
handle(result
.flatMap { maybeData in
maybeData.map(Result.success)
?? .failure(NSError(domain: "", code: 0, description: "error"))
})
}
}
func执行(然后句柄:@escaping(Result)->Void){
externalAPI.retrieveData{结果为
处理(结果)
.flatMap{maybeData in
maybeData.map(Result.success)
??失败(N错误(域:“”,代码:0,说明:“错误”))
})
}
}
或者如果我希望有人以后能够真正阅读:
func execute(then handle: @escaping (Result<Data, Error>) -> Void) {
externalAPI.retrieveData { result in
handle(result
.flatMap {
switch $0 {
case .some(let data): return .success(data)
case .none: return .failure(NSError(domain: "", code: 0, description: "error"))
}
}
)
}
}
func执行(然后句柄:@escaping(Result)->Void){
externalAPI.retrieveData{结果为
处理(结果)
.平面图{
转换$0{
case.some(让数据):return.success(数据)
case.none:返回.failure(n错误(域:“”,代码:0,说明:“错误”))
}
}
)
}
}
与您的开关相比,此开关的优点是您不必打开和重新包装以前的故障。您必须使用第二种方法,在异步完成处理程序中抛出是不可能的。开关中的数据
真的是可选的吗?顺便说一句,您的自定义错误是毫无意义的。我无法控制外部API结果,所以很遗憾,它是可选的。至于自定义错误,它是一个占位符,而不是真正的实现。谢谢你的帮助!如果API返回带有关联类型的枚举,则这些类型应该是非可选的。如果数据
为nil
则API必须返回。失败
传递错误。