7 minutes read
This is an updated version of the original article. I want to thank @joseanpg for the corrections and the idea regarding TextEncoder.
The sources of the demo used in this article are located here.
This is how our foreign imports from API.Web.Streams.purs look like:
We define a few important effects and values like WebStreamM, Response, Reader etc. Not all of them will be used but just for the case we expand our demo later. For now we’ll only see WebStreamM running, as this is our base “Effect”. In Haskell lingo: its kind (a metatype) is called ‘effect’ and it describes an effectful computation, like reading from a stream. Everything that’s not pure in Haskell has to be confined to some container or context. In the above case we have to isolate our unpure computation from the rest of the code that is pure, in PureScript’s definition of purity. This also means that all values generated within an unpure context can never leave it or be intermingled with the pure ones in any way. We can’t do this in PureScript, never! If you ask yourself why the name of the ‘context’ WebStreamEff ends with an Eff the answer is rather simple: it’s a Monad which wraps our effectful computations. In this case its the handling of web streams which are, of course, side-effects and everything else but not pure. So, they require a proper Monad to control them. No, please, do not leave my blog! I’m not going to teach you anything about monads here. I did it once and I deeply regret it.
Additionally there’s a function for creating new TextDecorders with different encodings as defined in this list from MDN.
For even more control of the stream flow and the decoding procedure we can use the decode function that either accepts a valid TextDecoder or creates a new one if we pass Nothing as argument.
In this code part we define a small mechanism that will read from stream and forward this data to the callback function from PureScript. Line 51 shows how we have to call this PureScript-function. The `returned` Promise from the original Reader (Line 41) has to be called inside an additional wrapper (Line 58) that will take care of it being correctly resolved while our nested callback at Line 51 continues to process data. Our TextReader, that we either pass as a non-null argument or immediately create at Line 34, is continuously consuming the incoming chunks at Line 49.
Of course, all this probably looks too convoluted and surely there could be a more elegant solution than mine, but that’s it for now.
This is the code of our Test App:
We define a (not very intelligent) Callback, instantiate a TextDecoder for UTF-8 and call the foreign import read to handle the incoming Web Stream from the given URL.
And this is how it looks like:
Well, there’s no need to advertise it more. Go and read Jake’s article! It’s an exciting technology and I can only hope that my examples from above aren’t doing any disservice to the PureScript community. When it comes to PureScript and/or Haskell I’m still a noob trying to learn something new each day (and night).