use*_*306 7 caching haskell 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
Run Code Online (Sandbox Code Playgroud)
并在某个小部件中:
renderDerp :: Widget
renderDerp = do
--these are used in the shakespeare files
lolBob <- handlerToWidget $ getBob
nutherBob <- handlerToWidget $ getBob
$(widgetFile "test")
Run Code Online (Sandbox Code Playgroud)
这会编译,但获取ID的查询仍会运行多次.
我究竟做错了什么?或者有没有更好的方法只能获得一次bob并在每个处理程序和小部件中使用他?
我对 Yesod 还很陌生,但我认为你只需要调整一下getBob
getBob :: Handler BobId
getBob = unCachedBobId <$> cached (CachedBobId <$> getBob')
Run Code Online (Sandbox Code Playgroud)
问题是您当前的getBob
函数以 开始其do
块a <- getBob'
。请记住,块对单子操作进行排序,因此实际上每次调用时do
您都会首先调用第一件事。具有讽刺意味的是,完成此操作后,您创建了一个处理程序的缓存版本,该版本返回您刚刚从 中获取的内容,但最终只查询该缓存版本一次(随后使用),然后它就超出了范围垃圾收集器得到它。getBob'
getBob
getBob'
c <- cached b
在我上面介绍的解决方案中,您可以将任何getBob'
给您的内容包装在CachedBobId
. 然后,您将该处理程序传递CachedBobId <$> getBob' :: Handler (CachedBobId BobId)
给cached
,这会返回另一个cached (CachedBobId <$> getBob')
相同类型的处理程序,但带有缓存。最后,您提取缓存处理程序为您提供的任何内容以取回Handler BobId
.
归档时间: |
|
查看次数: |
303 次 |
最近记录: |