Swift Vapor 3:使用wait()时检测到Eventloop错误

Swift Vapor 3:使用wait()时检测到Eventloop错误,swift,future,event-loop,vapor,vapor-fluent,Swift,Future,Event Loop,Vapor,Vapor Fluent,我正在努力理解如何批量保存获取的对象并将其存储到数据库中。将对象存储到数据库后,我希望返回查询结果。 我无法理解如何使用EventLoopFuture执行此操作,因为当我调用.wait()时,我收到错误消息: 前置条件失败:检测到错误:在EventLoop上不能调用wait() 作为我问题的一个例子: 我需要从外部端点获取实体(比如机场航班) 该调用的结果需要保存到数据库中。如果数据库中存在航班,则需要更新航班,否则需要创建航班 完成后,需要返回数据库中所有航班的列表 到目前为止,这是我得到

我正在努力理解如何批量保存获取的对象并将其存储到数据库中。将对象存储到数据库后,我希望返回查询结果。 我无法理解如何使用EventLoopFuture执行此操作,因为当我调用
.wait()
时,我收到错误消息:

前置条件失败:检测到错误:在EventLoop上不能调用wait()

作为我问题的一个例子:

  • 我需要从外部端点获取实体(比如机场航班)
  • 该调用的结果需要保存到数据库中。如果数据库中存在航班,则需要更新航班,否则需要创建航班
  • 完成后,需要返回数据库中所有航班的列表
到目前为止,这是我得到的,但这给了我一个错误:

func flights(on conn: DatabaseConnectable, customerName: String, flightType: FlightType) throws -> Future<[Flight]> {

    return Airport.query(on: conn).filter(\.customerName == customerName).first().flatMap(to: [Flight].self) { airport in
      guard let airport = airport else {
        throw Abort(.notFound)
      }

      guard let airportId = airport.id else {
        throw Abort(.internalServerError)
      }

      // Update items for customer
      let fetcher: AirportManaging?

      switch customerName.lowercased() {
      case "coolCustomer":
        fetcher = StoreOneFetcher()
      default:
        fetcher = nil
        debugPrint("Unhandled customer to fetch from!")
        // Do nothing
      }

      let completion = Flight.query(on: conn).filter(\.airportId == airportId).filter(\.flightType == flightType).all

      guard let flightFetcher = fetcher else { // No customer fetcher to get from, but still return whats in the DB
        return completion()
      }

      return try flightFetcher.fetchDataForAirport(customerName, on: conn).then({ (flights) -> EventLoopFuture<[Flight]> in
        flights.forEach { flight in
          _ = try? self.storeOrUpdateFlightRecord(flight, airport: airport, on: conn).wait()
        }
        return completion()
      })
    }
  }

  func storeOrUpdateFlightRecord(_ flight: FetcherFlight, airport: Airport, on conn: DatabaseConnectable) throws -> EventLoopFuture<Flight> {
    guard let airportId = airport.id else {
      throw Abort(.internalServerError)
    }

    return Flight.query(on: conn).filter(\.itemName == flight.itemName).filter(\.airportId == airportId).filter(\.flightType == flight.type).all().flatMap(to: Flight.self) { flights in
      if let firstFlight = flights.first {
        debugPrint("Found flight in database, updating...")
        return flight.toFlight(forAirport: airport).save(on: conn)
      }

      debugPrint("Did not find flight, saving new...")
      return flight.toFlight(forAirport: airport).save(on: conn)
    }
  }
func flights(在conn:DatabaseConnectable上,customerName:String,flightType:flightType)抛出->未来{
返回Airport.query(on:conn.filter(\.customerName==customerName).first().flatMap(to:[Flight].self){Airport in
警卫让机场=其他机场{
抛出中止(.notFound)
}
警卫让airportId=airport.id else{
抛出中止(.internalServerError)
}
//为客户更新项目
let fetcher:机场管理?
开关customerName.lowercased(){
案例“coolCustomer”:
fetcher=StoreOneFetcher()
违约:
fetcher=nil
debugPrint(“要从中提取的未处理客户!”)
//无所事事
}
let completion=Flight.query(on:conn).filter(\.airportId==airportId).filter(\.flightType==flightType).all
guard let flightFetcher=fetcher else{//没有要从中获取的客户fetcher,但仍然返回数据库中的内容
返回完成()
}
返回try flightFetcher.fetchDataForAirport(customerName,on:conn)。然后({(flights)->EventLoopFuture in
flights.forEach{flights in
_=try?self.storeOrUpdateFlightRecord(航班,机场:机场,接通:康涅狄格州)。等待()
}
返回完成()
})
}
}
func storeOrUpdateFlightRecord(u航班:FetcherFlight,机场:机场,在conn:DatabaseConnectable上)抛出->事件循环未来{
警卫让airportId=airport.id else{
抛出中止(.internalServerError)
}
返回Flight.query(on:conn).filter(\.itemName==Flight.itemName).filter(\.airportId==airportId).filter(\.flightType==Flight.type).all().flatMap(to:Flight.self){flights in
如果让firstFlight=flights.first{
debugPrint(“在数据库中找到航班,正在更新…”)
返回航班。起飞时间(机场:机场)。保存(接通:康涅狄格州)
}
debugPrint(“未找到航班,正在保存新…”)
返回航班。起飞时间(机场:机场)。保存(接通:康涅狄格州)
}
}
那么在线
中的问题是什么呢?self.storeOrUpdateFlightRecord(航班,机场:机场,接通:康涅狄格州)。等待()
。我不能调用
wait()
,因为它会阻止eventLoop,但是如果我调用
map
flatMap
我需要依次返回一个
EventLoopFuture
U
Flight
),我对此完全不感兴趣


我希望调用
self.storeOrUpdateFlightRecord
,并忽略结果。我该怎么做?

是的,你不能在
eventLoop
上使用
.wait()

在您的情况下,可以使用
flant
进行批处理操作

///flant在未来的数组上工作
返回航班.map{
试试self.storeOrUpdateFlightRecord($0,airport:airport,on:conn)
///因此,将未来的结果转化为无效
.转换(到:())
}
///然后运行扁平化,它也将返回未来
.展平(在:康涅狄格州)展平地图{
///然后做你想做的:)
返回完成()
}

太棒了。必须将其更改为
compactMap
并尝试?self.storeOrUpdateFlightRecord(…)因为闭包不能抛出,但它现在可以工作了!谢谢你的帮助。