Swift 如何处理完成闭包中的多个错误
我正在实现一个函数,它接受一个数组和一个完成闭包。我迭代数组中的项目,根据每个项目执行网络请求。当每个请求完成时,它将其结果附加到集合中 一旦所有请求都返回,函数的完成块将使用累积的集合进行调用 我的问题是,我不确定如何处理网络请求可能提供的(可能是多个)错误。有没有标准的方法来处理这种模式?首先想到的想法是:Swift 如何处理完成闭包中的多个错误,swift,closures,Swift,Closures,我正在实现一个函数,它接受一个数组和一个完成闭包。我迭代数组中的项目,根据每个项目执行网络请求。当每个请求完成时,它将其结果附加到集合中 一旦所有请求都返回,函数的完成块将使用累积的集合进行调用 我的问题是,我不确定如何处理网络请求可能提供的(可能是多个)错误。有没有标准的方法来处理这种模式?首先想到的想法是: 一旦一个网络请求的错误被给出,调用函数的完成闭包,结果为nil,错误为零 在所有网络请求都完成后,使用某种结构调用完成闭包,该结构包含成功完成的调用的结果和未成功完成的调用的错误 这
- 一旦一个网络请求的错误被给出,调用函数的完成闭包,结果为nil,错误为零
- 在所有网络请求都完成后,使用某种结构调用完成闭包,该结构包含成功完成的调用的结果和未成功完成的调用的错误
我在SWIFT 3.1中实现这一点。
< P>我不知道你的完成闭包是如何看起来的,但是你可以考虑使用<代码>枚举> /COD>,结果().< /P>有一个相关值。 如果像这样创建enum
:
enum ClosureResult {
case success([String])
case failure([String], [Error])
}
func yourFunction(items: [String], completion: (ClosureResult) -> Void) {
var completedItems = [String]()
var failedItems = [Error]()
for item in items {
//Do your network magic here
//if it succeeds add it to completedItems
//if it fails, add it to failedItems
}
//did we encounter any failures?
if failedItems.count > 0 {
//yes we did, return a .failure then
let failure = ClosureResult.failure(completedItems, failedItems)
completion(failure)
} else {
//no...return .success
let success = ClosureResult.success(completedItems)
completion(success)
}
}
根据网络查找是失败还是成功,您可以返回不同的值。请注意,在我的failure
案例中,我将传递一个Error
对象数组作为第二个参数,我不知道这是否适合您,但这只是为了说明您可以传递多个参数作为回报
如果然后使用closuresult
作为完成闭包的返回值,则可以在返回时在自己的块中对其执行切换
,并根据该值执行操作
因此,您的函数可以如下所示:
enum ClosureResult {
case success([String])
case failure([String], [Error])
}
func yourFunction(items: [String], completion: (ClosureResult) -> Void) {
var completedItems = [String]()
var failedItems = [Error]()
for item in items {
//Do your network magic here
//if it succeeds add it to completedItems
//if it fails, add it to failedItems
}
//did we encounter any failures?
if failedItems.count > 0 {
//yes we did, return a .failure then
let failure = ClosureResult.failure(completedItems, failedItems)
completion(failure)
} else {
//no...return .success
let success = ClosureResult.success(completedItems)
completion(success)
}
}
然后你可以这样使用它:
let items = ["a", "b", "c"]
yourFunction(items: items) { result in
switch result {
case .success(let okItems):
print(okItems)
case .failure(let okItems, let failedItems):
print(failedItems)
}
}
更新
你在评论中问:
我唯一关心的是,在您的示例中,网络请求在“a”和“c”上成功,而不是在“b”上成功,关闭结果包含关于哪个项失败的任何信息。在ClosureResult对象中返回项的元组和该项的网络结果而不仅仅是字符串是否合理
是的,这是有道理的。我刚才使用了String
和Error
作为示例,但是您也可以使用自己的类
我想,我要做的是,不使用元组,而是创建一个简单的类并返回它
例如:
struct ClosureError {
let item: String
let error: Error
}
然后您的closuresult
enum可以使用:
enum ClosureResult {
case success([String])
case failure([String], [ClosureError])
}
在yourFunction
中,遇到故障时,需要创建ClosureError
的新实例:
...
var failedItems = [ClosureError]()
...
for item in items {
//Do your network magic here
//if it succeeds add it to completedItems
//if it fails, add it to failedItems
let error = //create the error
let closureFailure = ClosureFailure(item, error)
failedItems.append(closureFailure)
}
...
最后,在开关中
您将知道哪些项目失败:
let items = ["a", "b", "c"]
yourFunction(items: items) { result in
switch result {
case .success(let okItems):
print(okItems)
case .failure(let okItems, let failedItems):
for closureError in failedItems {
print("item: \(closureError.item) has failed with error \(closureError.error)"
}
}
}
您可能应该为各个部分找到更好的名称:)
希望有意义,可以使用。< p>我不知道你的完成闭包看起来如何,但是你可以考虑使用<代码>枚举< /Cord>。 如果像这样创建
enum
:
enum ClosureResult {
case success([String])
case failure([String], [Error])
}
func yourFunction(items: [String], completion: (ClosureResult) -> Void) {
var completedItems = [String]()
var failedItems = [Error]()
for item in items {
//Do your network magic here
//if it succeeds add it to completedItems
//if it fails, add it to failedItems
}
//did we encounter any failures?
if failedItems.count > 0 {
//yes we did, return a .failure then
let failure = ClosureResult.failure(completedItems, failedItems)
completion(failure)
} else {
//no...return .success
let success = ClosureResult.success(completedItems)
completion(success)
}
}
根据网络查找是失败还是成功,您可以返回不同的值。请注意,在我的failure
案例中,我将传递一个Error
对象数组作为第二个参数,我不知道这是否适合您,但这只是为了说明您可以传递多个参数作为回报
如果然后使用closuresult
作为完成闭包的返回值,则可以在返回时在自己的块中对其执行切换
,并根据该值执行操作
因此,您的函数可以如下所示:
enum ClosureResult {
case success([String])
case failure([String], [Error])
}
func yourFunction(items: [String], completion: (ClosureResult) -> Void) {
var completedItems = [String]()
var failedItems = [Error]()
for item in items {
//Do your network magic here
//if it succeeds add it to completedItems
//if it fails, add it to failedItems
}
//did we encounter any failures?
if failedItems.count > 0 {
//yes we did, return a .failure then
let failure = ClosureResult.failure(completedItems, failedItems)
completion(failure)
} else {
//no...return .success
let success = ClosureResult.success(completedItems)
completion(success)
}
}
然后你可以这样使用它:
let items = ["a", "b", "c"]
yourFunction(items: items) { result in
switch result {
case .success(let okItems):
print(okItems)
case .failure(let okItems, let failedItems):
print(failedItems)
}
}
更新
你在评论中问:
我唯一关心的是,在您的示例中,网络请求在“a”和“c”上成功,而不是在“b”上成功,关闭结果包含关于哪个项失败的任何信息。在ClosureResult对象中返回项的元组和该项的网络结果而不仅仅是字符串是否合理
是的,这是有道理的。我刚才使用了String
和Error
作为示例,但是您也可以使用自己的类
我想,我要做的是,不使用元组,而是创建一个简单的类并返回它
例如:
struct ClosureError {
let item: String
let error: Error
}
然后您的closuresult
enum可以使用:
enum ClosureResult {
case success([String])
case failure([String], [ClosureError])
}
在yourFunction
中,遇到故障时,需要创建ClosureError
的新实例:
...
var failedItems = [ClosureError]()
...
for item in items {
//Do your network magic here
//if it succeeds add it to completedItems
//if it fails, add it to failedItems
let error = //create the error
let closureFailure = ClosureFailure(item, error)
failedItems.append(closureFailure)
}
...
最后,在开关中
您将知道哪些项目失败:
let items = ["a", "b", "c"]
yourFunction(items: items) { result in
switch result {
case .success(let okItems):
print(okItems)
case .failure(let okItems, let failedItems):
for closureError in failedItems {
print("item: \(closureError.item) has failed with error \(closureError.error)"
}
}
}
您可能应该为各个部分找到更好的名称:)
希望这是有意义的,可以使用。看看它,它看起来很有趣,可能是我最好的选择,但是如果我开始使用PromiseKit,那么我的功能的用户是否需要了解如何使用PromiseKit?我希望避免给用户增加任何额外的要求。我只是想知道,对于不使用PromiseKit的人来说,什么是正常的。这取决于您的要求,请咨询将使用此功能的人。另一种可能是创建操作,以便您可以构建依赖项等。我不确定您想要实现什么。看看它看起来很有趣,可能是我的最佳选择,但如果我开始使用PromiseKit,那么我的功能的用户是否需要了解如何使用PromiseKit?我希望避免给用户增加任何额外的要求。我只是想知道,对于不使用PromiseKit的人来说,什么是正常的。这取决于你的要求,请与使用此功能的人联系