如何使用yesod
我试图使用cached
函数来防止在不同的小部件和处理程序中的多个数据库查询:
newtype CachedBobId key
= CachedBobId { unCachedBobId :: key }
deriving Typeable
getBob' :: Handler BobId
getBob' = do
uncle <- runInputGet $ ireq textField "bobsuncle"
(Entity bob _) <- runDB $ getBy404 $ UniqueBob uncle
return bob
getBob :: Handler BobId
getBob = do
a <- getBob'
let b = return $ CachedBobId a
c <- cached b
return $ unCachedBobId c
并在某个小部件中:
renderDerp :: Widget
renderDerp = do
--these are used in the shakespeare files
lolBob <- handlerToWidget $ getBob
nutherBob <- handlerToWidget $ getBob
$(widgetFile "test")
这编译但查询得到ID仍然运行多次。
我究竟做错了什么? 或者有没有更好的方法来让鲍勃有一次并在每个处理程序和小部件中使用他?
我对Yesod很新,但我认为你只需要调整getBob
getBob :: Handler BobId
getBob = unCachedBobId <$> cached (CachedBobId <$> getBob')
问题是你当前的getBob
函数用a <- getBob'
启动它的do
块。 请记住, do
块列单子的操作,所以你实际上最终调用getBob'
每次第一件事getBob
被调用。 具有讽刺意味的是,在完成这些之后,您创建了一个处理程序的缓存版本,该处理程序返回刚刚从getBob'
获得getBob'
,但最终getBob'
查询该缓存版本一次(之后使用c <- cached b
),那么它就会超出范围,垃圾收集器就会获取它。
在上面提供的解决方案中,您可以将任何getBob'
在CachedBobId
提供给你的东西包装CachedBobId
。 然后,您将该处理程序CachedBobId <$> getBob' :: Handler (CachedBobId BobId)
传递给cached
,这会让您返回另一个cached (CachedBobId <$> getBob')
处理程序cached (CachedBobId <$> getBob')
,但具有缓存。 最后,你提取缓存的处理程序给你的任何东西,以获取Handler BobId
。
上一篇: How to use yesod per