计算流如何Future
在单个 Vapor 路由中从多个动作序列中分支出来,以返回一个简单String
Response
的指示退出哪个阶段?
Future
如果抛出错误,方法catch(_:)
、、catchMap(on:_:)
和可以执行;catchFlatMap(_:)
但是,到目前为止,我对任何 catch 方法的实验都无法Future
扩展动作序列。(参见API和文档)
注意:由于Vapor 3 Async 核心是建立在swift-nio之上的,所以 SwiftNIO 解决方案也很有趣。
例子
例如,考虑一个Future
序列,它将create
一个 db 条目、update
相同的 db 条目、query
(读取)该 db 条目,然后返回一些String
响应。
发布结构
{
"number": 0
}
public struct ExamplePipe: Codable {
public var id: UUID?
public var number: Int
init(number: Int) {
self.number = number
}
public func description() -> String {
return """
UUID: \(id?.uuidString ?? "nil.....-....-....-....-............")
{number:\(number)}
"""
}
}
// Database model for fetching and saving data via Fluent.
extension ExamplePipe: SQLiteUUIDModel {}
// Content convertable to/from HTTP message.
extension ExamplePipe: Content {}
// Database migration
extension ExamplePipe: Migration {}
// Dynamic HTTP routing parameter: `id`
extension ExamplePipe: Parameter {}
struct ExamplePipeController: RouteCollection {
func boot(router: Router) throws {
let pipelineRoutes = router.grouped("api", "pipeline")
// POST http://localhost:8080/api/pipeline/linear
pipelineRoutes.post(ExamplePipe.self, at: "linear", use: linearPost)
// POST http://localhost:8080/api/pipeline/nested
pipelineRoutes.post(ExamplePipe.self, at: "nested", use: nestedPost)
}
// …
}
场景:map
线性序列
// POST http://localhost:8080/api/example/pipeline/basic
func linearPost(_ request: Request, _ pipelineData: ExamplePipe)
throws -> Future<String> {
var s = "##### Linear Pipeline Data #####\n"
let mutableA = pipelineData
s += "## STAGE_A \(mutableA.description())\n"
let futureA: Future<ExamplePipe> = mutableA.create(on: request)
let futureB: Future<ExamplePipe> = futureA.flatMap(to: ExamplePipe.self) {
(nonmutableB: ExamplePipe) -> Future<ExamplePipe> in
var mutableB = nonmutableB
mutableB.number += 1
if mutableB.number == 2 {
print("POSSIBLE TO EXIT SEQUENCE AT STAGE B??")
}
s += "## STAGE_B \(mutableB.description())\n"
let futureB: Future<ExamplePipe> = mutableB.update(on: request)
return futureB
}
let futureC: Future<ExamplePipe?> = futureB.flatMap {
(nonmutableC: ExamplePipe) -> Future<ExamplePipe?> in
s += "## STAGE_C \(nonmutableC.description())\n"
if nonmutableC.id == nil {
print("POSSIBLE TO EXIT SEQUENCE AT STAGE C??")
}
let uuid = nonmutableC.id!
let futureC: Future<ExamplePipe?> = ExamplePipe
.query(on: request)
.filter(\ExamplePipe.id==uuid)
.first()
return futureC
}
let futureD: Future<String> = futureC.map(to: String.self) {
(nonmutableD: ExamplePipe?) -> String in
guard var mutableD = nonmutableD else {
s += "## STAGE_D ExamplePipe is NIL\n"
s += "#################################\n"
print(s)
return s
}
mutableD.number += 1
s += "## STAGE_D \(mutableD.description())\n"
s += "#################################\n"
print(s)
return s
}
return futureD
}
场景:map
嵌套序列
// POST http://localhost:8080/api/example/pipeline/nested
func nestedPost(_ request: Request, _ pipelineData: ExamplePipe)
throws -> Future<String> {
var s = "##### Nested Pipeline Data #####\n"
let mutableA = pipelineData
s += "## STAGE:A \(mutableA.description())\n"
let futureA: Future<ExamplePipe> = mutableA.create(on: request)
let futureD: Future<String> = futureA.flatMap {
(nonmutableB: ExamplePipe) -> Future<String> in
var mutableB = nonmutableB
mutableB.number += 1
if mutableB.number == 2 {
print("POSSIBLE TO EXIT SEQUENCE AT STAGE B??")
}
s += "## STAGE:B \(mutableB.description())\n"
let futureB: Future<ExamplePipe> = mutableB.update(on: request)
let futureDD: Future<String> = futureB.flatMap {
(nonmutableC: ExamplePipe) -> Future<String> in
s += "## STAGE:C \(nonmutableC.description())\n"
if nonmutableC.id == nil {
print("POSSIBLE TO EXIT SEQUENCE AT STAGE C??")
}
let uuid = nonmutableC.id!
let futureC: Future<ExamplePipe?> = ExamplePipe
.query(on: request)
.filter(\ExamplePipe.id==uuid)
.first()
let futureDDD: Future<String> = futureC.map(to: String.self) {
(nonmutableD: ExamplePipe?) -> String in
guard var mutableD = nonmutableD else {
s += "## STAGE:D ExamplePipe is `nil`\n"
s += "#################################\n"
print(s)
return s
}
mutableD.number += 1
s += "## STAGE:D \(mutableD.description())\n"
s += "#################################\n"
print(s)
return s
}
return futureDDD
}
return futureDD
}
return futureD
}