Jak se rozdělit o ‚budoucnosti‘ sekvence v jediném Vapor trase?

hlasů
0

Jak je možné výpočet větev toku ven z řady různých Futureakcí, v jediném Vapor trase vrátit jednoduchý String Responsecož naznačuje, jaké fázi byl ukončen?

Je to možné v Swift 4 na par 3?

Futuremetod catch(_:), catchMap(on:_:)a catchFlatMap(_:)může spustit, pokud je vyvolána chyba; Nicméně, můj experimenty doposud s žádným přístupem úlovek již nejsou schopni větvit posloupnost Futureakcí. (viz API & Dokumenty )

Poznámka: Vzhledem k tomu, par 3 asynchronní jádro je postaven na vrcholu rychlé-nio , roztok SwiftNIO by bylo také zajímavé.

Příklad

Například, zvážit Futuresekvenci, která bude createzáznam db, updatestejné db vstup, query(čtení) vstup db, a pak se vrátit nějaké Stringreakci.

Struktura pro vysílání

{
  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)
  }
  // …
}

Scénář: maplineární sekvence

// 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
}

Scénář: mapVnořené Sekvence

// 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
}
Položena 21/07/2018 v 00:39
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
0

Par 3 asynchronní jádra , který je postaven na vrcholu rychlé-nio nezdá se, že žádný přímý mechanismus (y), se rozdělit na vícenásobné Future sekvence. Futureje typealiaspro SwiftNIO EventLoopFuture.

Níže jsou uvedeny dva možné Swift přístupy založené buď EXIT sekvenci nebo v podstatě „přeskočit“ zbývající sekvence. Oba přístupy mohou vrátit některé smysluplné plný Stringklientovi.

Přístup 1: Konec sekvence (vyvolá Debuggablechybu)

Je-li cílem je vrátit nějaké smysluplné informace klientovi při ukončení sekvence, pak jednou z možností je hodit Debuggablechybu opuštění Futureposloupnosti. Debuggableumožňuje na odpověď, která obsahuje důvod. V tomto případě se Stringstává JSON hodnota „důvod“.

Založit:

public struct ExamplePipeError: Error {
  let comment: String

  init(comment: String) {
    self.comment = comment
  }
}

extension ExamplePipeError: Debuggable {
  // `Debuggable` Required Attributes
  public var identifier: String {
    return "\(ExamplePipeError.readableName)"
  }

  public var reason: String {
    return "\(comment)"
  }
}


private func checkNumber(number: Int, mustNotBe: Int, comment: String) throws {
  if number == mustNotBe {
    let error = ExamplePipeError(comment: comment)
    throw error
  }
}

Použití:

let futureB: Future<ExamplePipe> = futureA.flatMap(to: ExamplePipe.self) { 
  (nonmutableB: ExamplePipe) throws -> Future<ExamplePipe> in
  var mutableB = nonmutableB
  mutableB.number += 1
  s += "## STAGE_B \(mutableB.description())\n"
  try self.checkNumber(
    number: mutableB.number, 
    mustNotBe: 2, 
    comment: "STAGE_B requires number which is not 2."
  )
  let futureB: Future<ExamplePipe> = mutableB.update(on: request)
  return futureB
}

Klient obdrží:

{"error":true,"reason":"STAGE_B requires number which is not 2."}

Přístup 2: Skok přes Sequence fází (používá stavovou proměnnou)

Založit:

enum ExamplePipeState {
  case ok
  case exitedStageB
  case exitedStageC
}

Použití:

func linearStageFlagPost(_ request: Request, _ pipelineData: ExamplePipe) 
                         throws -> Future<String> {
  var state: ExamplePipeState = .ok 
  var s = ""
  s += "##### Pipeline Data: `linear-stage-flag` #####\n"

  let mutableA = pipelineData
  s += "## STAGE_A \(mutableA.description())\n"
  let futureA: Future<ExamplePipe> = mutableA.create(on: request)

  let futureB = futureA.flatMap { 
    (nonmutableB: ExamplePipe) -> Future<ExamplePipe> in
    var mutableB = nonmutableB
    mutableB.number += 1
    s += "## STAGE_B \(mutableB.description())\n"
    if mutableB.number == 2 {
      s += " … EXIT/SKIP SEQUENCE AT STAGE B.\n"
      state = ExamplePipeState.exitedStageB
      let skipB: Future<ExamplePipe> = request.eventLoop.future(nonmutableB)
      return skipB
    }
    let futureB = mutableB.update(on: request)
    return futureB
  }

  let futureC: Future<ExamplePipe?> = futureB.flatMap { 
    (nonmutableC: ExamplePipe) -> Future<ExamplePipe?> in
    guard state == .ok else {
      s += "## STAGE_C SKIPPED\n"
      return request.eventLoop.future(nonmutableC)
    }
    s += "## STAGE_C \(nonmutableC.description())\n"
    if nonmutableC.number == 3 {
      s += " … EXIT/SKIP SEQUENCE AT STAGE C.\n"
      state = ExamplePipeState.exitedStageC
      let skipC: Future<ExamplePipe?> = request.eventLoop.future(nil)
      return skipC
    }
    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
    switch state {
    case .ok:
      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

    case .exitedStageB:
      s += "## STAGE_D after exiting STAGE_B and skipping STAGE_C\n"
      s += "##########################\n"
      print(s)
      return s

    case .exitedStageC:
      s += "## STAGE_D after exiting STAGE_C\n"
      s += "##########################\n"
      print(s)
      return s

    }
  }

  return futureD
}

Klient obdrží:

##### Pipeline Data: `linear-stage-flag` #####
## STAGE_A UUID: nil.....-....-....-....-............ 
{number:1}
## STAGE_B UUID: 904156A2-BC1A-42B1-AC89-0C4A598EA4BB 
{number:2}
 … EXIT/SKIP `linear-try-catch` SEQUENCE AT STAGE B.
## STAGE_C SKIPPED `linear-stage-flag` SEQUENCE AT STAGE C
## STAGE_D after exiting STAGE_B and skipping STAGE_C
##########################
Odpovězeno 24/07/2018 v 23:26
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more