如何使用 BoltsSwift 更好地链接任务?
How to better chain tasks using BoltsSwift?
第一次使用 Bolts,我几乎可以理解它们是如何工作的,但是我确信必须有一种更简洁的方法来完成我正在做的事情。
在我的示例中,我想下载一个包含类别的 JSON,将它们导入 Core Data,然后下载一个包含成分的 JSON 并将它们也导入。事情需要按此顺序发生,因为我的解析器要求 Category
对象在解析 Ingredient
对象之前已经存在。
我正在使用 BoltsSwift 以避免嵌套块,所以我将 "downloader" 和 "importer" return 设为 Task
.
网络调用(使用Moya):
static func downloadJSON(target: MoyaAPI) -> BoltsSwift.Task<JSONArray> {
let taskCompletionSource = TaskCompletionSource<JSONArray>()
requestJSONArray(target, success: { (jsonArray) in
taskCompletionSource.set(result: jsonArray)
}, error: { (error) in
taskCompletionSource.set(error: error)
}, failure: { (moyaError) in
taskCompletionSource.set(error: moyaError)
})
return taskCompletionSource.task
}
解析部分(使用Groot):
func importCategories(from json: JSONArray) -> BoltsSwift.Task<[Category]> {
let taskCompletionSource = TaskCompletionSource<[Category]>()
do {
let categories: [Category] = try objects(fromJSONArray: json, inContext: managedObjectContext)
taskCompletionSource.set(result: categories)
} catch {
taskCompletionSource.set(error: error)
}
return taskCompletionSource.task
}
所以后来当我尝试将这 4 个任务实际链接在一起时,我想出了这个:
NetworkAdapter.downloadJSON(target: .categories).continueOnSuccessWithTask { (json) -> Task<[Category]> in
return importer.importCategories(from: json)
}.continueOnSuccessWith { (categories) in
return NetworkAdapter.downloadJSON(target: .ingredients).continueOnSuccessWithTask(continuation: { (json) -> Task<[Ingredient]> in
return importer.importIngredients(from: json)
})
}
这行得通,但我觉得语法可以更具可读性。有人可以解释一下将这 4 个任务很好地链接起来的正确方法是什么吗?
您应该能够在第二次 JSON 下载到顶层后提取嵌套任务,从而使代码更简洁:
NetworkAdapter.downloadJSON(target: .categories)
.continueOnSuccessWithTask { (json) in
return importer.importCategories(from: json)
}
.continueOnSuccessWithTask { (_) in
return NetworkAdapter.downloadJSON(target: .ingredients)
}
.continueOnSuccessWithTask { (json) in
return importer.importIngredients(from: json)
}
(如果编译器感到困惑,您可能需要在闭包中重新添加 return 类型声明。)
如果以上方法适合您,您可以使用内联闭包进一步精简代码:
NetworkAdapter.downloadJSON(target: .categories)
.continueOnSuccessWithTask { importer.importCategories(from: [=11=]) }
.continueOnSuccessWith { NetworkAdapter.downloadJSON(target: .ingredients) }
.continueOnSuccessWithTask { importer.importIngredients(from: [=11=]) }
第一次使用 Bolts,我几乎可以理解它们是如何工作的,但是我确信必须有一种更简洁的方法来完成我正在做的事情。
在我的示例中,我想下载一个包含类别的 JSON,将它们导入 Core Data,然后下载一个包含成分的 JSON 并将它们也导入。事情需要按此顺序发生,因为我的解析器要求 Category
对象在解析 Ingredient
对象之前已经存在。
我正在使用 BoltsSwift 以避免嵌套块,所以我将 "downloader" 和 "importer" return 设为 Task
.
网络调用(使用Moya):
static func downloadJSON(target: MoyaAPI) -> BoltsSwift.Task<JSONArray> {
let taskCompletionSource = TaskCompletionSource<JSONArray>()
requestJSONArray(target, success: { (jsonArray) in
taskCompletionSource.set(result: jsonArray)
}, error: { (error) in
taskCompletionSource.set(error: error)
}, failure: { (moyaError) in
taskCompletionSource.set(error: moyaError)
})
return taskCompletionSource.task
}
解析部分(使用Groot):
func importCategories(from json: JSONArray) -> BoltsSwift.Task<[Category]> {
let taskCompletionSource = TaskCompletionSource<[Category]>()
do {
let categories: [Category] = try objects(fromJSONArray: json, inContext: managedObjectContext)
taskCompletionSource.set(result: categories)
} catch {
taskCompletionSource.set(error: error)
}
return taskCompletionSource.task
}
所以后来当我尝试将这 4 个任务实际链接在一起时,我想出了这个:
NetworkAdapter.downloadJSON(target: .categories).continueOnSuccessWithTask { (json) -> Task<[Category]> in
return importer.importCategories(from: json)
}.continueOnSuccessWith { (categories) in
return NetworkAdapter.downloadJSON(target: .ingredients).continueOnSuccessWithTask(continuation: { (json) -> Task<[Ingredient]> in
return importer.importIngredients(from: json)
})
}
这行得通,但我觉得语法可以更具可读性。有人可以解释一下将这 4 个任务很好地链接起来的正确方法是什么吗?
您应该能够在第二次 JSON 下载到顶层后提取嵌套任务,从而使代码更简洁:
NetworkAdapter.downloadJSON(target: .categories)
.continueOnSuccessWithTask { (json) in
return importer.importCategories(from: json)
}
.continueOnSuccessWithTask { (_) in
return NetworkAdapter.downloadJSON(target: .ingredients)
}
.continueOnSuccessWithTask { (json) in
return importer.importIngredients(from: json)
}
(如果编译器感到困惑,您可能需要在闭包中重新添加 return 类型声明。)
如果以上方法适合您,您可以使用内联闭包进一步精简代码:
NetworkAdapter.downloadJSON(target: .categories)
.continueOnSuccessWithTask { importer.importCategories(from: [=11=]) }
.continueOnSuccessWith { NetworkAdapter.downloadJSON(target: .ingredients) }
.continueOnSuccessWithTask { importer.importIngredients(from: [=11=]) }