简体   繁体   中英

Vapor 4 Get String from EventLoopFuture<String>

I'm working on a web, where I have "Posts" that belong to a specific "Category", so, when Im list the post, I will like to show the Category name, so I did:

private func getCategory(from id: UUID, andRequest req: Request) -> EventLoopFuture<String> {

        let categoryField = BlogCategoryModel.find(id, on: req.db).map { cat in
            return cat?.title ?? "Unknown"
        }

        return categoryField
    }

So, I'm dont know how to use this EventLoopFuture<String> to get the String that I need.

UPDATE :

Im Going to give you more context.

So, I'm have a controller to show a list of elements:

protocol ListController: ModelController {
    func listView(req: Request) throws -> EventLoopFuture<View>
    
    func listTable(_ models: [Model], req: Request) -> Table
    func listContext(req: Request, table: Table) -> ListContext
}

public struct ListContext: Encodable {

    public let title: String
    public let table: Table

    internal init(title: String, table: Table) {
        self.title = title
        self.table = table
    }
}


extension ListController {

    func listContext(req: Request, table: Table) -> ListContext {
        .init(title: Model.name.plural.capitalized, table: table)
    }
    
    func listView(req: Request) throws -> EventLoopFuture<View> {
        Model.query(on: req.db)
            .all()
            .map { listTable($0, req: req) }
            .flatMap { table in
                req.view.render("Common/List", listContext(req: req, table: table))
            }
    }
}

and Then, I can use this protocol to show any kind of model. In this case, I'm want to show the blog with the category father:

struct BlogPostAdminController: ListController{

    typealias Model = BlogPostModel
    
    func listTable(_ models: [Model], req: Request) -> Table {
        Table(columns: ["image", "title", "category"], rows: models.map { model in
            TableRow(id: model.id!.uuidString, cells: [
                TableCell(type: .image, model.image),
                TableCell(model.title),
                TableCell(getCategory(from: model.$category.id, andRequest: req)),
            ])
        })
    }

    private func getCategory(from id: UUID, andRequest req: Request) -> EventLoopFuture<String> {

        let categoryField = BlogCategoryModel.find(id, on: req.db).map { cat in
            return cat?.title ?? "Unknown"
        }

        return categoryField
    }
}

Your question wasn't clear.

Are you calling the method somewhere or registered as a route?

In case you're calling the method: Tip: You need to learn more about (Future / Promise) The idea is you need to map it in order to get the value asynchronously (Which means: if getting the value is not instant you shouldn't block the thread waiting for the value).

Registered as a route: The route will return your value in response body and you can decode it or read it directly as String.

Without knowing a bit more on where you're calling this function from it's difficult to know but I would try this if all you need is to turn the BlogCategoryModel DB call into an EventLoopFuture<String> .

    private func getCategory(from id: UUID, andRequest req: Request) -> EventLoopFuture<String> {
    
        return BlogCategoryModel.find(id, on: req.db)
            .flatMap { cat in
                return cat?.title ?? "Unknown"
            }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM