Can I run asynchronous actions sequentially in EventM? #462
-
I could send a custom event to take care of asynchronous actions, but it will become unmanageable quickly. I wonder whether there is something like javascript promise API for EventM. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 6 replies
-
If you're wondering whether this is provided by Brick itself, then no, there is no such API. I would not recommend attempting to orchestrate something like that from The |
Beta Was this translation helpful? Give feedback.
-
The way I often do this sort of thing is something like the following sketch: -- From base:
import Control.Monad (forever)
import Control.Concurrent (forkIO)
-- From stm:
import Control.Concurrent.STM (atomically)
import Control.Concurrent.STM.TChan (newTChanIO, readTChan, writeTChan)
-- From brick:
import Brick.BChan (BChan, writeBChan)
data WorkerRequest =
DoStuff ...
| DoMoreStuff ...
data WorkerResponse =
StuffReady ...
| MoreStuffReady ...
data Worker =
Worker { workerChan :: TChan WorkerRequest }
startWorker :: BChan WorkerResponse -> IO Worker
startWorker respChan = do
reqChan <- newTChanIO
void $ forkIO $ workerLoop reqChan respChan
return $ Worker reqChan
sendWorkerRequest :: Worker -> WorkerRequest -> IO ()
sendWorkerRequest (Worker ch) req = atomically (writeTChan ch req)
workerLoop :: TChan WorkerRequest -> BChan WorkerResponse -> IO ()
workerLoop reqChan respChan = forever $ do
req <- atomically $ readTChan reqChan
writeBChan =<< doWork req
doWork :: WorkerRequest -> IO WorkerResponse
doWork (DoStuff ...) = return $ StuffReady ...
doWork (DoMoreStuff ...) = return $ MoreStuffReady ... Once you have that kind of skeleton, it's very easy to add new request and response constructors, add cases to |
Beta Was this translation helpful? Give feedback.
If you're wondering whether this is provided by Brick itself, then no, there is no such API. I would not recommend attempting to orchestrate something like that from
EventM
. I find it actually quite manageable to use a custom event approach and have a separate thread that accepts "requests" (e.g. over aTChan
), does work, and then sends "responses" back to the main event loop in the form of custom app events. That is how Brick is intended to be used, although you could certainly implement your own async scheme; it would ultimately need to use custom application events anyway since that's the only way to trigger …