1

Hedis 的文档中,给出了使用该pubSub函数的示例:

pubSub :: PubSub -> (Message -> IO PubSub) -> Redis ()

pubSub (subscribe ["chat"]) $ \msg -> do
    putStrLn $ "Message from " ++ show (msgChannel msg)
    return $ unsubscribe ["chat"]

鉴于pubSub返回 a ,是否可以从回调外部在代码中进一步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

或者,有没有办法json在回调中使用 Scotty's?到目前为止,我还无法做到这一点。

4

1 回答 1

2

我会假设您打算进一步缩进该行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 函数是否在收到消息之前阻塞,如果不是这样,那么你可以使用 anMVar代替:

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
于 2021-06-07T15:25:58.687 回答