【问题标题】:Error when mapping an EventLoopFuture<Type> to an expected Type将 EventLoopF​​uture<Type> 映射到预期类型时出错
【发布时间】:2020-11-11 06:44:27
【问题描述】:

我尝试过映射、平面映射、创建EventLoopFuturePost 等...我正在尝试返回两个db.queries,它们创建要在req.view.render 上呈现的单独的内容数组,它返回一个EventLoopFuture&lt;View&gt;

我的错误是:Cannot convert value of type 'EventLoopFuture&lt;[Posts]&gt;' to expected argument type '[Posts]'.

这是路由器调用的代码:

func blogView(req: Request) throws -> EventLoopFuture<View> {
    struct PageContext: Encodable {
        var posts: [Posts]
        var categories: [Categories]
        var title: String
    }
    struct Posts: Encodable {
        var posts: BlogPostModel.ViewContext
        var category: BlogCategoryModel.ViewContext
    }
    struct Categories: Encodable {
        var categoryList: BlogCategoryModel.ViewContext
    }

    let posts = BlogPostModel.query(on: req.db)
        .sort(\.$date, .descending)
        .with(\.$category)
        .all()
        .mapEach {Posts(posts: $0.viewContext, category: $0.category.viewContext)}
    let categories = BlogCategoryModel.query(on: req.db)
        .sort(\.$title)
        .all()
        .mapEach {Categories(categoryList: $0.viewContext)}
    let returnContext = PageContext(posts: posts,categories: categories, title: categories)
    return req.view.render("Blog/Frontend/Blog", returnContext)
}

编辑:下面是我的评论。这个 sn-p 返回帖子(和相关的类别)。尝试在返回中添加第二个db.query

func blogView(req: Request) throws -> EventLoopFuture<View> {
    struct Context: Encodable {
        struct PostWithCategory: Encodable {
            var category: BlogCategoryModel.ViewContext
            var post: BlogPostModel.ViewContext }
        let title: String
        let items: [PostWithCategory]
    }

    return BlogPostModel.query(on: req.db)
        .sort(\.$date, .descending)
        .with(\.$category)
        .all()
        .mapEach {
            Context.PostWithCategory(category: $0.category.viewContext, post: $0.viewContext) 
        }
        .flatMap {
            let context = Context(title: "Blog Posts", items: $0)
            return req.view.render("Blog/Frontend/Blog", context)
        }
}

【问题讨论】:

  • 看起来很清楚。 posts 是一个 Future,因此您不能将其分配为 PageContext 的 posts。我不知道蒸汽,但在我看来,您的 Future 有一系列操作员,您需要获取该 Future 的 输出 - 它需要实际 run。您需要响应 Future 的运行,例如在whenComplete 运算符中。
  • 是的,我明白了......我正在努力使用蒸汽语法。我正在尝试使帖子变平。我会在 .mapeach 之后的链中使用 .flatMap() 来展平未来的帖子以获取帖子,但是,它会在 .mapEach 上引发错误,抱怨没有推断出 NewValue。
  • 我不认为是语法给你带来了问题。我认为您没有掌握什么是 Future 及其随附的管道 。这是一连串的操作,将在未知的未来某个时间发生。在该链的末端——不是在链外,而是在 in 作为它的最终操作符——你可以接收到从管道末端弹出的值。这就是您要附加 whenComplete 运算符的地方,然后您将在 whenComplete 运算符中创建您的 Posts 对象。
  • 但请注意,您的代码的最后一行揭示了一个更大的误解。您不能返回此管道生成的值,原因很简单,管道将在将来运行。这就是未来!该方法将在 Future 有机会运行并生成其输出之前返回。因此,如果我没记错的话,您在这里的整个方法都是在吠叫一棵非常错误的树。 (我只是根据我对“异步”意味着什么以及 Future 在其他框架(如 Combine)中的了解进行猜测。)
  • 是的...我明白了...这是有效的代码...我只是想在返回之前向链中添加第二个 db.query...这个 sn -p 获取我的帖子(和相关类别)并将值返回给分配给请求的 Future。我想要做的也是返回类别数组(不仅仅是分配给帖子的那些)。请查看我刚才在编辑中添加的 sn-p...

标签: swift vapor swift-nio


【解决方案1】:

您的问题是您的PageContext 类型具有[Post][Categories] 类型的属性,但您尝试使用EventLoopFuture&lt;[Post]&gt;EventLoopFuture&lt;[Categories]&gt; 初始化PageContext。你可以做的是使用NIO的.and方法将2个EventLoopFuture对象组合成1个:

posts.and(categories) // EventLoopFuture<([Post], [Categories])>

然后您可以映射到这个新的 EventLoopFuture 以获取元组并创建您的 PageContext 实例:

return posts.and(categories).flatMap { posts, categories in
    let returnContext = PageContext(posts: posts, categories: categories, title: "Blog Posts")
    return req.view.render("Blog/Frontend/Blog", context)
}

【讨论】:

  • 是的!谢谢迦勒。我知道我需要将这两个未来结合起来……只是不知道如何将两者同时展平。真的很感谢你也布置了完整的关闭! @Caleb++。 ?
猜你喜欢
  • 2021-03-24
  • 2021-10-30
  • 2021-04-23
  • 1970-01-01
  • 2021-11-21
  • 2020-03-25
  • 2021-11-23
  • 2017-05-12
  • 2015-04-21
相关资源
最近更新 更多