问题描述
在documentation for Hedis中,给出了一个使用pubSub
函数的例子:
pubSub :: PubSub -> (Message -> IO PubSub) -> Redis ()
pubSub (subscribe ["chat"]) $ \msg -> do
putStrLn $ "Message from " ++ show (msgChannel msg)
return $ unsubscribe ["chat"]
鉴于 pubSub
返回一个 Redis ()
,是否仍然可以在代码的更深处,从回调外部重新使用此 msg
消息?
我正在从在 pubSub
monad 中运行的 Scotty 端点调用 ScottyM
,并且应该返回(长话短说)一个 json msg
myEndpoint :: ScottyM ()
myEndpoint =
post "/hello/world" $ do
data :: MyData <- jsonData
runRedis redisConn $ do
pubSub (subscribe ["channel"]) $ \msg -> do
doSomethingWith msg
return $ unsubscribe ["channel"]
-- how is it possible to retrieve `msg` from here?
json $ somethingBuiltFromMsg
或者,有没有办法在回调中使用 Scotty 的 json
?到目前为止,我还无法做到这一点。
解决方法
我假设您打算用 json
进一步缩进该行。
您可以在 IO
中使用可变变量,例如IORef
:
import Data.IORef (newIORef,writeIORef,readIORef)
import Control.Monad.IO.Class (liftIO)
myEndpoint :: ScottyM ()
myEndpoint =
post "/hello/world" $ do
data :: MyData <- jsonData
msgRef <- liftIO (newIORef Nothing)
runRedis redisConn $ do
pubSub (subscribe ["channel"]) $ \msg -> do
writeIORef msgRef (Just msg)
return $ unsubscribe ["channel"]
Just msg <- liftIO (readIORef msgRef)
json $ doSomethingWithMsg msg
编辑:我想我真的不知道 runRedis 函数是否在收到消息之前阻塞,如果不是这种情况,那么您可以使用 MVar
代替:
import Control.Concurrent.MVar (putMVar,takeMVar,newEmptyMVar)
import Control.Monad.IO.Class (liftIO)
myEndpoint :: ScottyM ()
myEndpoint =
post "/hello/world" $ do
data :: MyData <- jsonData
msgVar <- liftIO newEmptyMVar
runRedis redisConn $ do
pubSub (subscribe ["channel"]) $ \msg -> do
putMVar msgVar msg
return $ unsubscribe ["channel"]
msg <- liftIO (takeMVar msgVar)
json $ doSomethingWithMsg msg