Как сгладить несколько запросов в Vapor - PullRequest
1 голос
/ 07 марта 2020

Мне нужно выполнить множество запросов к разным таблицам и вернуть результаты в одном ответе. Мне интересно, можно ли сгладить чрезвычайно вложенную функцию?

final class CodeController {
    internal func indexCodes(_ req: Request) throws -> EventLoopFuture<Response> {
        CodeCountry.query(on: req).sort(\.name).all().flatMap { countries -> EventLoopFuture<Response> in
            CodeFloor.query(on: req).sort(\.name).all().flatMap { floors -> EventLoopFuture<Response> in
                CodeRegion.query(on: req).sort(\.name).all().flatMap { regions -> EventLoopFuture<Response> in
                    CodeObjectType.query(on: req).sort(\.name).all().flatMap { objectTypes -> EventLoopFuture<Response> in
                        CodePropertyType.query(on: req).sort(\.name).all().flatMap { propertyTypes -> EventLoopFuture<Response> in
                            CodeRooms.query(on: req).sort(\.name).all().flatMap { rooms -> EventLoopFuture<Response> in
                                let codes = CodesContent(
                                    countries: countries,
                                    floors: floors,
                                    regions: regions,
                                    objectTypes: objectTypes,
                                    propertyTypes: propertyTypes,
                                    rooms: rooms
                                )

                                return codes.encode(status: .ok, for: req)
                            }
                        }
                    }
                }
            }
        }
    }
}

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Возможно, это не самый красивый код, но я думаю, что это решает проблему. Мне понравился подход @ Nick к представлению новой модели данных в виде коллекции, поэтому я буду делать то же самое. Вы можете объединить два фьючерса и получить один. Это происходит от SwiftNIO

let futureThingOne: Future<ThingOne> = ...
let futureThingTwo: Future<ThingTwo> = ...
let futureBothThings: Future<(ThingOne, ThingTwo)> = futureThingOne.and(futureThingTwo)

Таким образом, объединяя фьючерсы, поступающие из запросов, вы можете построить уплощенную структуру.

struct Codes: Content {
    let countries: [CodeCountry]
    let floors: [CodeFloor]
    let regions: [CodeRegion]
    let objectTypes: [CodeObjectType]
    let propertyTypes: [CodePropertyType]
    let rooms: [CodeRooms]

    static func codes(req: Request) -> Future<Codes> {
        let futureCountries = CodeCountry.query(on: req).sort(\.name).all()
        let futureFloors = CodeFloor.query(on: req).sort(\.name).all()
        let futureRegions = CodeRegion.query(on: req).sort(\.name).all()
        let futureObjectTypes = CodeObjectType.query(on: req).sort(\.name).all()
        let futurePropertyTypes = CodePropertyType.query(on: req).sort(\.name).all()
        let futureRooms = CodeRooms.query(on: req).sort(\.name).all()

        let combined = futureCountries.and(futureFloors).and(futureRegions).and(futureObjectTypes).and(futurePropertyTypes).and(futureRooms)
       return combined.map {
            Codes.init(
                countries: $0.0.0.0.0.0,
                floors: $0.0.0.0.0.1,
                regions: $0.0.0.0.1,
                objectTypes: $0.0.0.1,
                propertyTypes: $0.0.1,
                rooms: $0.1
            )
        }

    }
}
1 голос
/ 08 марта 2020

Попробуйте изменить CodesContent на Future s как:

struct CodesContent:Content
{
    let countries:Future<[CodeCountry]>
    let floors:Future<[CodeFloor]>
    let regions:Future<[CodeRegionCodeObjectType]>
    let objectTypes:Future<[CodeObjectType]>
    let propertyTypes:Future<[CodePropertyType]>
    let rooms:Future<[CodeRoom]>
}

Затем измените код контроллера на:

final class CodeController {
    internal func indexCodes(_ req: Request) throws -> EventLoopFuture<Response> {
        let countries = CodeCountry.query(on: req).sort(\.name).all()
        let floors = CodeFloor.query(on: req).sort(\.name).all()
        let regions = CodeRegion.query(on: req).sort(\.name).all()
        let objectTypes = CodeObjectType.query(on: req).sort(\.name).all()
        let propertyTypes = CodePropertyType.query(on: req).sort(\.name).all()
        let rooms = CodeRooms.query(on: req).sort(\.name).all()
        let codes = CodesContent(
            countries: countries,
            floors:floors,
            regions:regions,
            objectTypes:objectTypes,
            propertyTypes:propertyTypes,
            rooms:rooms
        )
        return codes.encode(status:.ok, for:req)
    }
}
...