{"componentChunkName":"component---src-blog-post-tsx","path":"/nodejs-streams","result":{"data":{"site":{"siteMetadata":{"title":"lordie"}},"orgContent":{"html":"<p>This is the first topic recommend by the <a href=\"https://www.nodecertification.com/\">node certification guide</a>, I really like using streams but the Node api is bit cumbersome compared to my previous experiences. The api provides two main classes, <code>Writable</code> and <code>Redable</code>, there's also <code>Duplex</code> that just inherits from both of them and <code>Transform</code> which is just a special form of <code>Duplex</code> that facilitates applying functions to streams.</p><pre><code class=\"hljs language-js\"><span class=\"hljs-keyword\">const</span> { Writable, Redable, Duplex, Transform } = <span class=\"hljs-built_in\">require</span>(<span class=\"hljs-string\">\"stream\"</span>)\n\n<span class=\"hljs-keyword\">const</span> outStream = <span class=\"hljs-keyword\">new</span> Writable({\n  <span class=\"hljs-function\"><span class=\"hljs-title\">write</span>(<span class=\"hljs-params\">chunk, encoding, callback</span>)</span> {\n    <span class=\"hljs-built_in\">console</span>.log(chunk.toString())\n    callback()\n  },\n})\n\n<span class=\"hljs-keyword\">const</span> inStream = <span class=\"hljs-keyword\">new</span> Readable({\n  <span class=\"hljs-function\"><span class=\"hljs-title\">read</span>(<span class=\"hljs-params\">size</span>)</span> {\n    <span class=\"hljs-built_in\">this</span>.push(<span class=\"hljs-built_in\">String</span>.fromCharCode(<span class=\"hljs-built_in\">this</span>.currentCharCode++))\n    <span class=\"hljs-keyword\">if</span> (<span class=\"hljs-built_in\">this</span>.currentCharCode > <span class=\"hljs-number\">90</span>) {\n      <span class=\"hljs-built_in\">this</span>.push(<span class=\"hljs-literal\">null</span>)\n    }\n  },\n})\n\n<span class=\"hljs-keyword\">const</span> inoutStream = <span class=\"hljs-keyword\">new</span> Duplex({\n  <span class=\"hljs-function\"><span class=\"hljs-title\">write</span>(<span class=\"hljs-params\">chunk, encoding, callback</span>)</span> {\n    <span class=\"hljs-built_in\">console</span>.log(chunk.toString())\n    callback()\n  },\n\n  <span class=\"hljs-function\"><span class=\"hljs-title\">read</span>(<span class=\"hljs-params\">size</span>)</span> {\n    <span class=\"hljs-built_in\">this</span>.push(<span class=\"hljs-built_in\">String</span>.fromCharCode(<span class=\"hljs-built_in\">this</span>.currentCharCode++))\n    <span class=\"hljs-keyword\">if</span> (<span class=\"hljs-built_in\">this</span>.currentCharCode > <span class=\"hljs-number\">90</span>) {\n      <span class=\"hljs-built_in\">this</span>.push(<span class=\"hljs-literal\">null</span>)\n    }\n  },\n})\n\n<span class=\"hljs-keyword\">const</span> upperCaseTr = <span class=\"hljs-keyword\">new</span> Transform({\n  <span class=\"hljs-function\"><span class=\"hljs-title\">transform</span>(<span class=\"hljs-params\">chunk, encoding, callback</span>)</span> {\n    <span class=\"hljs-built_in\">this</span>.push(chunk.toString().toUpperCase())\n    callback()\n  },\n})</code></pre><p>The <code>Pipe()</code> method on <code>Redable</code> streams can be used compose them with <code>Writable</code> streams, but the <code>pipeline()</code> utility provides a much nicer way of doing this.</p><pre><code class=\"hljs language-js\">a.pipe(read).pipe(duplex).pipe(write)\n\npipeline(read, duplex, write, <span class=\"hljs-function\"><span class=\"hljs-params\">err</span> =></span> {})</code></pre><p>Streams, like every javascript api, comes with a few event handlers</p><pre><code class=\"hljs language-js\">readable.on(<span class=\"hljs-string\">\"data\"</span>, <span class=\"hljs-function\"><span class=\"hljs-params\">chunk</span> =></span> {\n  writable.write(chunk)\n})\n\nreadable.on(<span class=\"hljs-string\">\"end\"</span>, <span class=\"hljs-function\">() =></span> {\n  writable.end()\n})</code></pre><p><code>ObjectMode</code> is an unexpected cool property that let's you mark your stream output/input type as an <code>Object</code> instead of <code>Buffer</code>, which is the default.</p><pre><code class=\"hljs language-js\"><span class=\"hljs-keyword\">const</span> arrayToObject = <span class=\"hljs-keyword\">new</span> Transform({\n  <span class=\"hljs-attr\">readableObjectMode</span>: <span class=\"hljs-literal\">true</span>,\n  <span class=\"hljs-attr\">writableObjectMode</span>: <span class=\"hljs-literal\">true</span>,\n  <span class=\"hljs-function\"><span class=\"hljs-title\">transform</span>(<span class=\"hljs-params\">chunk, encoding, callback</span>)</span> {\n    <span class=\"hljs-keyword\">const</span> obj = {}\n    <span class=\"hljs-keyword\">for</span> (<span class=\"hljs-keyword\">let</span> i = <span class=\"hljs-number\">0</span>; i &#x3C; chunk.length; i += <span class=\"hljs-number\">2</span>) {\n      obj[chunk[i]] = chunk[i + <span class=\"hljs-number\">1</span>]\n    }\n    <span class=\"hljs-built_in\">this</span>.push(obj)\n    callback()\n  },\n})</code></pre><p>the <code>chunk</code> argument in any stream with <code>writableObjectMode: true</code> will be an <code>Object</code> :)</p><p>A lot of Node core libraries implement the <code>stream</code> api, so using it feels pretty natural. Thanks to <a href=\"https://jscomplete.com/learn/node-beyond-basics/node-streams\">jscomplete</a> and <a href=\"https://heynode.com/tutorial/what-stream\">heynode</a> for clear and well structure resources.</p>","metadata":{"title":"Node.js Streams","date":"2020-04-23T19:36:00.000Z"}}},"pageContext":{"slug":"/nodejs-streams","tags":[],"previous":{"slug":"/nodejs-certification","metadata":{"title":"Node.js certification"}},"next":{"slug":"/tutor","metadata":{"title":"Supoprted Syntax"}}}},"staticQueryHashes":["2841359383"]}