UNPKG

28.1 kBMarkdownView Raw
1# Async Endpoint
2
3![Async Endpoint Logo](logo.png)
4
5**Asynchronous Endpoints**, especially when paired with a **functional style of programming**,
6provide a sound method of writing programs in JavaScripts that are
7
8 - testable
9 - maintainable
10 - extendable
11 - composeable
12 - easy to reason about
13 - standard based*
14
15This repository provides a brief intoduction to asynchronous endpoints\*\*, along with a helper library `async-endpoint` to help make a few things easier.
16
17## Table of contents
18
19* <a href="#introduction">Introduction</a>
20
21 * <a href="#introduction-synchronous-endpoints">Synchronous Endpoints</a>
22 * <a href="#introduction-synchronous-iteration">Synchronous Iteration</a>
23 * <a href="#introduction-asynchronous-iteration">Asynchronous Iteration</a>
24 * <a href="#introduction-asynchronous-input">Asynchronous Input</a>
25 * <a href="#import">Import</a>
26 * <a href="#application-programming-interface">API</a>
27# <a name="introduction"></a>Introduction
28
29Many programming languages use the concept of functions as [entry points](https://en.wikipedia.org/wiki/Entry_point) to transfer control between programs.
30
31## <a name="introduction-synchronous-endpoints"></a> Synchronous Endpoints
32
33In javascript, this is as simple as writing a function and calling it:
34
35**Example 1**
36
37```javascript
38const program = function() {
39 console.log("hello world");
40};
41
42program();
43//logs "hello world"
44```
45
46Taking a queue from functional programming, we can remove the logging side affect from the main program
47into a separate **render** function that logs the result retuned from running:
48
49**Example 2**
50
51```javascript
52const render = console.log;
53
54const program = function() {
55 return "hello world";
56};
57
58render(program());
59//logs "hello world"
60```
61
62## <a name="introduction-synchronous-iteration"></a> Synchronous Iteration
63
64Provided that our render function expects an iterator,
65We can construct our program with a **generator function** to yeild multiple results:
66
67**Example 3**
68
69```javascript
70const render = iterator => {
71 //as the result is an iterator
72 //we iterate though it and log each subsequent result
73 for (const result of iterator) {
74 console.log(result);
75 }
76};
77
78const program = function*() {
79 yield "hello";
80 yield "world";
81};
82
83render(program());
84//logs "hello"
85//logs "world"
86```
87
88## <a name="introduction-asynchronous-iteration"></a> Asynchronous Iteration
89
90When using **asynchronous generators**, we can **await** asynchronous APIs,
91though we must again make sure to modify our fetch function.
92
93**Example 4**
94
95```javascript
96const render = async asynchronousIterator => {
97 //we use the "for await" construct for Asynchronous Iterators
98 for await (const result of asynchronousIterator) {
99 console.log(result);
100 }
101};
102
103const program = async function*() {
104 yield "fetching...";
105 yield await fetch("https://www.google.com");
106 yield "results fetched.";
107};
108render(program());
109//logs "fetching..."
110//logs result from fetch.
111//logs "results fetched."
112```
113
114## <a name="introduction-asynchronous-input"></a> Asynchronous Input and Interactive Programs
115
116With a few small tricks, asynchronous generators can as fully interactive programs.
117
118We'll need a pair of functions: well call them "request" and "respond".
119
120When a program calles _request_, it will return a promise.
121This promise will then be fulfilled with the input of the next call to _respond_.
122While you can create these functions yourself,
123a method of creating them is included with the `async-endpoint` library.
124
125```javascript
126import { channel } from "async-endpoint";
127const [request, respond] = channel();
128```
129
130By convention, we'll pass two arguments to our asynchronous generator function:
131
132 - an _init_ object, which may or may not be ignored
133 - the aforementioned _request_ function
134
135```javascript
136const program = async function *(init, request){
137 ...
138}
139```
140
141Finally, we need to connect the _respond_ object to user input.
142If running in a browser, you could simply attach it to the window object:
143
144```javascript
145window.respond = respond;
146```
147
148Or, if running in node, you can use the included `inputConsole` function:
149
150```javascript
151import { inputConsole } from "async-endpoint";
152inputConsole(respond);
153```
154
155Puttig it all together, we can write an interactive program like this:
156(Note that instead of defining a render function, we're using the
157generic `renderer` from the `async-endpoit` library instead of writing our own this time).
158
159**Example 5**
160
161```javascript
162import { channel, inputConsole, renderer } from "async-endpoint";
163
164const render = renderer();
165
166const program = async function*(init, request) {
167 yield "What's your name?";
168 yield `Hello ${await request()}`;
169};
170
171const [request, respond] = channel();
172
173inputConsole(respond);
174
175render(program(undefined, request)); //the init object will be ignored
176//logs "
177```
178# <a name="import"></a>Import
179
180There are a few ways to import this into your project.
181
182## Pre-Ecmascript Modules
183
184### Common JS
185
186The package's main file is a compiled common JS file.
187
188```javascript
189const AsyncEndpoint = require("async-endpoint");
190```
191
192```javascript
193const AsyncEndpoint = require("async-endpoint/common.js"); //also works
194```
195
196This _should_ work with file bundlers, though I haven't had a chance to test it.
197
198```javascript
199import * as AsyncEndpoint from = "async-endpoint/common.js";
200```
201
202### Browser
203
204```html
205 <script src = ".../async-endpoint/browser.js"></script>
206 <script>
207 alert(typeof window.AsyncEndpoint);
208 </script>
209```
210
211## Ecmascript Modules
212
213Ecmascript modules are available in two flavors of ecmascript modules:
214
215### MJS
216
217In a node application, the "import" keyword can be used to import the package.
218
219```javascript
220 //index.mjs
221 import * as AsyncEndpoint from "async-endpoint/mjs";
222```
223
224As of this writing, node requires the the "experimental-modules" and
225"harmony_async_iteration" flags to be set, but this will change once a the
226"import" and "asynchronous iterator" features hae landed.
227
228```bash
229node --experimental-modules --harmony_async_iteration index.mjs
230```
231
232If you wish to avoid experimental the features, use the above **common.js** module.
233
234### JS
235
236In a browser application, the "import" keyword can be used to import the package.
237
238When using ".mjs" files, a server may fail to serve the proper "application/javascript"
239mime type causing the application to fail. As such, the "js" folder is included.
240
241
242```html
243 <script>
244 import * as AsyncEndpoint from "async-endpoint/js";
245 <script>
246 alert(typeof window.AsyncEndpoint);
247 </script>
248 </script>
249```
250
251As of this writing, only Chrome supports the necessary import and asynchronous interation features
252necessary to get this to work.
253
254To ensure compatibility with other browsers use the above **browser.js** module.
255You can also re-bundle either the flow, js, or mjs folders.
256
257# <a name="application-programming-interface"></a> API
258## Members
259
260<dl>
261<dt><a href="#channel">channel</a><code><a href="#AsyncPair">AsyncPair</a></code></dt>
262<dd><p>creates a pair of asynchronous functions used to transfer objects between programs</p>
263</dd>
264</dl>
265
266## Functions
267
268<dl>
269<dt><a href="#composePrograms">composePrograms(request, ...programs)</a><code>AsynchornousIterator</code></dt>
270<dd><p>composes programs sequentially with a single input</p>
271</dd>
272<dt><a href="#creates an iterator whose values are mapped from another">creates an iterator whose values are mapped from another(iterator, mapper)</a><code>AsynchornousIterator</code></dt>
273<dd></dd>
274<dt><a href="#executes a provided funcition for each item of an iterator">executes a provided funcition for each item of an iterator(iterator, handler)</a><code>undefined</code></dt>
275<dd></dd>
276<dt><a href="#filter">filter(iterator, filterer)</a><code>AsynchornousIterator</code></dt>
277<dd><p>creates an iterator whose values are filtered from another</p>
278</dd>
279<dt><a href="#reduce">reduce(iterator, reducer, [inital], [condition], [resetInitial])</a><code>AsynchornousIterator</code></dt>
280<dd><p>creates an iterator whose values are reduced from another</p>
281</dd>
282<dt><a href="#pause">pause(milliseconds, value)</a><code>Promise</code></dt>
283<dd><p>returns a resolved promise after a given amount of time
284useful for pausing asynchronous programs</p>
285</dd>
286<dt><a href="#composeAsyncTransformer">composeAsyncTransformer(last, first)</a><code><a href="#AsyncTransformer">AsyncTransformer</a></code></dt>
287<dd><p>composes two asynchoronous transformers</p>
288</dd>
289<dt><a href="#createQueue">createQueue(...initial)</a><code><a href="#PushPair">PushPair</a></code></dt>
290<dd><p>create a queue iterator</p>
291</dd>
292<dt><a href="#createStack">createStack(...initial)</a><code><a href="#PushPair">PushPair</a></code></dt>
293<dd><p>create a stack iterator</p>
294</dd>
295<dt><a href="#createProgramQueue">createProgramQueue()</a><code><a href="#PushPair">PushPair</a></code></dt>
296<dd><p>identity program that outputs what ever is input
297Like &quot;queue&quot;, but accepts program as input</p>
298</dd>
299<dt><a href="#createProgramStack">createProgramStack()</a><code><a href="#PushPair">PushPair</a></code></dt>
300<dd><p>identity program that outputs what ever is input
301Like &quot;queue&quot;, but accepts program as input</p>
302</dd>
303<dt><a href="#take">take(iterator, num, [skip])</a><code>Promise.&lt;Array&gt;</code></dt>
304<dd><p>extract items from iterator as array</p>
305</dd>
306<dt><a href="#takeWhile">takeWhile(iterator, accept, [skip])</a><code>Promise.&lt;Array&gt;</code></dt>
307<dd><p>extract first set of items that match a given condition as an array</p>
308</dd>
309<dt><a href="#identity">identity([delay], request)</a><code>AsynchronousIterator</code></dt>
310<dd><p>program that outputs what ever is put throught</p>
311</dd>
312<dt><a href="#continuousOutput">continuousOutput([sample])</a><code>AsynchronousIterator</code></dt>
313<dd><p>program that takes no input and contiuously outputs result of calling function</p>
314</dd>
315<dt><a href="#renderer">renderer([...targets])</a><code><a href="#AsyncRenderFunction">AsyncRenderFunction</a></code></dt>
316<dd><p>creates a render function that renders yeilded results from programs
317to any number of target functions. If no targets are given, objects will be rendered
318using &quot;console.log&quot;
319Can be used as a &quot;passthrough&quot; (see &quot;createQueue&quot; example)</p>
320</dd>
321<dt><a href="#tee">tee(...programs)</a><code><a href="#AsyncRenderFunction">AsyncRenderFunction</a></code></dt>
322<dd><p>creates a render function whos&#39;s values are teed on to given
323It may be advantageous to use this along side a programQueue</p>
324</dd>
325<dt><a href="#inputConsole">inputConsole(respond)</a></dt>
326<dd><p>send input typed into console to a PairedRespond function</p>
327</dd>
328<dt><a href="#inputPipe">inputPipe(respond)</a></dt>
329<dd><p>send input piped to console to a PairedRespond function</p>
330</dd>
331</dl>
332
333## Typedefs
334
335<dl>
336<dt><a href="#PairedRequest">PairedRequest</a><code>Promise.&lt;*&gt;</code></dt>
337<dd><p>a function that receives it&#39;s response from a paired PairedRespond function</p>
338</dd>
339<dt><a href="#PairedRespond">PairedRespond</a> : <code>function</code></dt>
340<dd><p>a function that sends it&#39;s input to a paired PairedRequest function</p>
341</dd>
342<dt><a href="#AsyncPair">AsyncPair</a> : <code>Array</code></dt>
343<dd><p>a pair of paired PairedRequest and PairedRespond functions</p>
344</dd>
345<dt><a href="#AsyncTransformer">AsyncTransformer</a><code>*</code></dt>
346<dd><p>stateless asynchronous function that transforms input without side effects</p>
347</dd>
348<dt><a href="#Program">Program</a><code>AsynchronousIterator</code></dt>
349<dd><p>an iteractive program</p>
350</dd>
351<dt><a href="#AsyncRenderFunction">AsyncRenderFunction</a> : <code>function</code></dt>
352<dd><p>a function that renders values from a given [Asynchronous] Iterator</p>
353</dd>
354<dt><a href="#PushPair">PushPair</a> : <code>Array</code></dt>
355<dd><p>an iterator and a paired function to add to it</p>
356</dd>
357</dl>
358
359<a name="channel"></a>
360
361## channel ⇒ [<code>AsyncPair</code>](#AsyncPair)
362creates a pair of asynchronous functions used to transfer objects between programs
363
364**Kind**: global variable
365**Returns**: [<code>AsyncPair</code>](#AsyncPair) - array of paired functions
366**Example**
367```js
368import {channel} from "async-endpoint";
369const [request, respond] = channel();
370const main = async()=>{
371 setTimeout(()=>{
372 respond("hello");
373 })
374 console.log(await request());
375}
376main();
377//logs "hello"
378```
379<a name="composePrograms"></a>
380
381## composePrograms(request, ...programs) ⇒ <code>AsynchornousIterator</code>
382composes programs sequentially with a single input
383
384**Kind**: global function
385**Returns**: <code>AsynchornousIterator</code> - resulting iterator
386
387| Param | Type | Description |
388| --- | --- | --- |
389| request | [<code>PairedRequest</code>](#PairedRequest) | request function for input |
390| ...programs | [<code>Program</code>](#Program) | programs to be composed sequentially |
391
392**Example**
393```js
394import {composePrograms} from "async-endpoint";
395import porgram1, program1, program3 from "....js";
396const [request, respond] = channel();
397const program = composePrograms(request, program1, program2, program3);
398window.respond = respond;
399```
400<a name="creates an iterator whose values are mapped from another"></a>
401
402## creates an iterator whose values are mapped from another(iterator, mapper) ⇒ <code>AsynchornousIterator</code>
403**Kind**: global function
404**Returns**: <code>AsynchornousIterator</code> - resulting iterator
405
406| Param | Type | Description |
407| --- | --- | --- |
408| iterator | <code>AsynchornousIterator</code> | iterator to be mapped |
409| mapper | [<code>AsyncTransformer</code>](#AsyncTransformer) | transformation for individual items |
410
411**Example**
412```js
413import {map, continuousOutput}, from "async-endpoint";
414let i = 0;
415const mapped = map(continuousOutput(()=>i++), (n) => n + 2);
416const main = async ()=>{
417 for await(item of mapped){
418 console.log(item);
419 }
420}
421main();
422logs "2"
423logs "3"
424logs "4"
425...
426```
427<a name="executes a provided funcition for each item of an iterator"></a>
428
429## executes a provided funcition for each item of an iterator(iterator, handler) ⇒ <code>undefined</code>
430**Kind**: global function
431
432| Param | Type | Description |
433| --- | --- | --- |
434| iterator | <code>AsynchornousIterator</code> | iterator |
435| handler | [<code>AsyncTransformer</code>](#AsyncTransformer) | provided function |
436
437**Example**
438```js
439import {forEach, continuousOutput}, from "async-endpoint";
440let i = 0;
441forEach(continuousOutput(()=>i++, console.log));
442main();
443logs "2"
444logs "3"
445logs "4"
446...
447```
448<a name="filter"></a>
449
450## filter(iterator, filterer) ⇒ <code>AsynchornousIterator</code>
451creates an iterator whose values are filtered from another
452
453**Kind**: global function
454**Returns**: <code>AsynchornousIterator</code> - filtered iterator
455
456| Param | Type | Description |
457| --- | --- | --- |
458| iterator | <code>AsynchornousIterator</code> | iterator to be filtered |
459| filterer | <code>function</code> | boolean filtering function |
460
461**Example**
462```js
463import {filter, continuousOutput} from "async-endpoint";
464let i = 0;
465const filtered =filter(continuousOutput(()=>i++), (n)=>n%2);
466const main = async ()=>{
467 for await(item of filtered){
468 console.log(item);
469 }
470}
471main();
472logs "1"
473logs "3"
474logs "5"
475```
476<a name="reduce"></a>
477
478## reduce(iterator, reducer, [inital], [condition], [resetInitial]) ⇒ <code>AsynchornousIterator</code>
479creates an iterator whose values are reduced from another
480
481**Kind**: global function
482**Returns**: <code>AsynchornousIterator</code> - reduced iterator
483
484| Param | Type | Default | Description |
485| --- | --- | --- | --- |
486| iterator | <code>AsynchornousIterator</code> | | iterator to be reduced |
487| reducer | <code>function</code> | | reducing function |
488| [inital] | <code>\*</code> | | initial object to reduce into |
489| [condition] | <code>function</code> | <code>(item, initial) &#x3D;&gt; false</code> | boolean filtering function indicating when to start new reduction phase |
490| [resetInitial] | <code>function</code> | <code>()&#x3D;&gt;initial</code> | method to reset/replace initial reduction object |
491
492**Example**
493```js
494import {reduce, continuousOutput} from "async-endpoint";
495let i = 0;
496const reduced = reduce(continuousOutput(()=>i++) , (previous, current)=>previous.push(current),[], (x)=!(x%5), ()=>([]));
497const main = async ()=>{
498 for await(item of reduced){
499 console.log(item);
500 }
501}
502main();
503logs "[0]"
504logs "[1, 2, 3, 4, 5]"
505 ...
506```
507<a name="pause"></a>
508
509## pause(milliseconds, value) ⇒ <code>Promise</code>
510returns a resolved promise after a given amount of time
511useful for pausing asynchronous programs
512
513**Kind**: global function
514**Returns**: <code>Promise</code> - promise fulfilled with value
515
516| Param | Type | Description |
517| --- | --- | --- |
518| milliseconds | <code>Number</code> | time to pause |
519| value | <code>\*</code> | optional returned value |
520
521**Example**
522```js
523import {pause} from "async-endopint.js";
524const main = async ()=>{
525 console.log("hello");
526 await pause(1000);
527 console.log("goodbye");
528}
529main();
530//logs "hello"
531//logs "goodbye" (after 1 second)
532```
533<a name="composeAsyncTransformer"></a>
534
535## composeAsyncTransformer(last, first) ⇒ [<code>AsyncTransformer</code>](#AsyncTransformer)
536composes two asynchoronous transformers
537
538**Kind**: global function
539**Returns**: [<code>AsyncTransformer</code>](#AsyncTransformer) - asynchonous compositon of current and pre
540
541| Param | Type | Description |
542| --- | --- | --- |
543| last | [<code>AsyncTransformer</code>](#AsyncTransformer) | transformer to apply last |
544| first | [<code>AsyncTransformer</code>](#AsyncTransformer) | transformer to apply first |
545
546**Example**
547```js
548import {composeAsyncTransformer} from "async-endopint.js";
549const t1 = async (x)=>`<${x}>`;
550const t2 = async (x)=>`[${x}]`;
551const t = composeAsyncTransformer(t1, t2);
552t("hello").then(console.log);
553//logs "<[hello]>"
554```
555<a name="createQueue"></a>
556
557## createQueue(...initial) ⇒ [<code>PushPair</code>](#PushPair)
558create a queue iterator
559
560**Kind**: global function
561**Returns**: [<code>PushPair</code>](#PushPair) - queue and push function
562
563| Param | Type | Description |
564| --- | --- | --- |
565| ...initial | <code>\*</code> | initial items in queue |
566
567**Example**
568```js
569import {createQueue, channel, renderer, renderer as createPassThrough} from "async-endpoint";
570import porgram1, program1, program3 from "....js";
571const [queue, push] createQueue();
572const passthrough = createPassThrough(push);
573passthrough(porgram1(), program2(), program3());
574const render = renderer();
575render(queue);
576```
577<a name="createStack"></a>
578
579## createStack(...initial) ⇒ [<code>PushPair</code>](#PushPair)
580create a stack iterator
581
582**Kind**: global function
583**Returns**: [<code>PushPair</code>](#PushPair) - stack and push function
584
585| Param | Type | Description |
586| --- | --- | --- |
587| ...initial | <code>\*</code> | initial items on stack |
588
589**Example**
590```js
591import {createStack, channel, renderer, renderer as createPassThrough} from "async-endpoint";
592import porgram1, program1, program3 from "....js";
593const [stack, push] createStack();
594const passthrough = createPassThrough(push);
595passthrough(porgram1(), program2(), program3());
596const render = renderer();
597render(stack);
598```
599<a name="createProgramQueue"></a>
600
601## createProgramQueue() ⇒ [<code>PushPair</code>](#PushPair)
602identity program that outputs what ever is input
603Like "queue", but accepts program as input
604
605**Kind**: global function
606**Returns**: [<code>PushPair</code>](#PushPair) - iterator and push function
607**Example**
608```js
609import {createProgramQueue, channel, renderer} from "async-endpoint";
610import porgram1, program1, program3 from "....js";
611const [queue, push] = createProgramQueue();
612push(porgram1(), program2(), program3());
613const render = renderer();
614render(queue);
615```
616<a name="createProgramStack"></a>
617
618## createProgramStack() ⇒ [<code>PushPair</code>](#PushPair)
619identity program that outputs what ever is input
620Like "queue", but accepts program as input
621
622**Kind**: global function
623**Returns**: [<code>PushPair</code>](#PushPair) - iterator and push function
624**Example**
625```js
626import {createProgramStack, channel, renderer} from "async-endpoint";
627import porgram1, program1, program3 from "....js";
628const [stack, push] = createProgramStack();
629push(porgram1(), program2(), program3());
630const render = renderer();
631render(stack);
632```
633<a name="take"></a>
634
635## take(iterator, num, [skip]) ⇒ <code>Promise.&lt;Array&gt;</code>
636extract items from iterator as array
637
638**Kind**: global function
639**Returns**: <code>Promise.&lt;Array&gt;</code> - stack and push function
640
641| Param | Type | Default | Description |
642| --- | --- | --- | --- |
643| iterator | <code>AsynchronousIterator</code> | | iterator from which to take |
644| num | <code>Number</code> | | number of items to take from iterator |
645| [skip] | <code>Number</code> | <code>0</code> | number of items to skip before taking |
646
647**Example**
648```js
649import {take, continuousOutput} from "async-endpoint";
650let i = 0;
651take(continuousOutput(()=>i++), 3,1).then(taken=>console.log(taken));
652//logs "[1,2,3]"
653```
654<a name="takeWhile"></a>
655
656## takeWhile(iterator, accept, [skip]) ⇒ <code>Promise.&lt;Array&gt;</code>
657extract first set of items that match a given condition as an array
658
659**Kind**: global function
660**Returns**: <code>Promise.&lt;Array&gt;</code> - stack and push function
661
662| Param | Type | Default | Description |
663| --- | --- | --- | --- |
664| iterator | <code>AsynchronousIterator</code> | | iterator from which to take |
665| accept | <code>function</code> | | boolean filtering function indicating whether to allow item |
666| [skip] | <code>Number</code> | <code>0</code> | number of items to skip before taking |
667
668**Example**
669```js
670import {takeWhile, continuousOutput} from "async-endpoint";
671let i = 0;
672takeWhile(continuousOutput(()=>i++), x => x < 5, 2).then(taken=>console.log(taken));
673//logs "[2,3,4]"
674```
675<a name="identity"></a>
676
677## identity([delay], request) ⇒ <code>AsynchronousIterator</code>
678program that outputs what ever is put throught
679
680**Kind**: global function
681**Returns**: <code>AsynchronousIterator</code> - resulting iterator
682
683| Param | Type | Default | Description |
684| --- | --- | --- | --- |
685| [delay] | <code>\*</code> | <code>0</code> | delay between sending output |
686| request | [<code>PairedRequest</code>](#PairedRequest) | | request function for input |
687
688**Example**
689```js
690import {identity, renderer channel} from "async-endpoint";
691const [request, respond] = channel();
692identity(undefined, request);
693window.respond = respond
694```
695<a name="continuousOutput"></a>
696
697## continuousOutput([sample]) ⇒ <code>AsynchronousIterator</code>
698program that takes no input and contiuously outputs result of calling function
699
700**Kind**: global function
701**Returns**: <code>AsynchronousIterator</code> - resulting iterator
702
703| Param | Type | Default | Description |
704| --- | --- | --- | --- |
705| [sample] | <code>\*</code> | <code>()&#x3D;&gt;{}</code> | function whose result to output |
706
707**Example**
708```js
709import {continuousOutput, renderer} from "async-endpoint";
710const render = renderer();
711render(continuousOutput(()=>"hello"))
712logs "hello" (continously)
713...
714```
715<a name="renderer"></a>
716
717## renderer([...targets]) ⇒ [<code>AsyncRenderFunction</code>](#AsyncRenderFunction)
718creates a render function that renders yeilded results from programs
719to any number of target functions. If no targets are given, objects will be rendered
720using "console.log"
721Can be used as a "passthrough" (see "createQueue" example)
722
723**Kind**: global function
724**Returns**: [<code>AsyncRenderFunction</code>](#AsyncRenderFunction) - asychronous render function
725
726| Param | Type | Description |
727| --- | --- | --- |
728| [...targets] | <code>function</code> | request function for input |
729
730**Example**
731```js
732import {renderer, continuousOutput} from "async-input.js";
733const render = renderer();
734render(continuousOutput);
735//logs "0"
736//logs "1"
737...
738```
739<a name="tee"></a>
740
741## tee(...programs) ⇒ [<code>AsyncRenderFunction</code>](#AsyncRenderFunction)
742creates a render function whos's values are teed on to given
743It may be advantageous to use this along side a programQueue
744
745**Kind**: global function
746**Returns**: [<code>AsyncRenderFunction</code>](#AsyncRenderFunction) - asychronous render function
747
748| Param | Type | Description |
749| --- | --- | --- |
750| ...programs | [<code>Program</code>](#Program) | programs to be sent values |
751
752**Example**
753```js
754import {tee, continousOutput, renderer} from "async-endpoint";
755import porgram1, program1, program3 from "....js";
756const instance1 = program1();
757const instance2 = program2();
758const instance3 = program3();
759const render = renderer();
760render(instance1, instance2, instance3)
761const renderTee = tee(porgram1, program1, program3)
762renderTee(continousOutput())
763```
764<a name="inputConsole"></a>
765
766## inputConsole(respond)
767send input typed into console to a PairedRespond function
768
769**Kind**: global function
770
771| Param | Type | Description |
772| --- | --- | --- |
773| respond | [<code>PairedRespond</code>](#PairedRespond) | request function for input |
774
775**Example**
776```js
777import {inputConsole, identity, channel, renderer} from "async-endpoint";
778const [request, respond] = creteAsyncPair();
779const render = renderer();
780render(identity(undefined, request))
781inputConsole(respond);
782```
783<a name="inputPipe"></a>
784
785## inputPipe(respond)
786send input piped to console to a PairedRespond function
787
788**Kind**: global function
789
790| Param | Type | Description |
791| --- | --- | --- |
792| respond | [<code>PairedRespond</code>](#PairedRespond) | request function for input |
793
794**Example**
795```js
796import {inputPipe, identity, channel, renderer} from "async-endpoint";
797const [request, respond] = creteAsyncPair();
798const render = renderer();
799render(identity(undefined, request))
800inputPipe(respond);
801```
802<a name="PairedRequest"></a>
803
804## PairedRequest ⇒ <code>Promise.&lt;\*&gt;</code>
805a function that receives it's response from a paired PairedRespond function
806
807**Kind**: global typedef
808**Returns**: <code>Promise.&lt;\*&gt;</code> - response from respond reunction
809<a name="PairedRespond"></a>
810
811## PairedRespond : <code>function</code>
812a function that sends it's input to a paired PairedRequest function
813
814**Kind**: global typedef
815
816| Param | Type | Description |
817| --- | --- | --- |
818| response | <code>\*</code> | response for request function |
819
820<a name="AsyncPair"></a>
821
822## AsyncPair : <code>Array</code>
823a pair of paired PairedRequest and PairedRespond functions
824
825**Kind**: global typedef
826**Properties**
827
828| Name | Type | Description |
829| --- | --- | --- |
830| 0 | [<code>PairedRequest</code>](#PairedRequest) | request function |
831| 1 | [<code>PairedRespond</code>](#PairedRespond) | respond function |
832
833<a name="AsyncTransformer"></a>
834
835## AsyncTransformer ⇒ <code>\*</code>
836stateless asynchronous function that transforms input without side effects
837
838**Kind**: global typedef
839**Returns**: <code>\*</code> - transformed input
840
841| Param | Type | Description |
842| --- | --- | --- |
843| input | <code>\*</code> | input |
844
845<a name="Program"></a>
846
847## Program ⇒ <code>AsynchronousIterator</code>
848an iteractive program
849
850**Kind**: global typedef
851**Returns**: <code>AsynchronousIterator</code> - asynchronous iterator result
852
853| Param | Type | Description |
854| --- | --- | --- |
855| init | <code>\*</code> | |
856| request | [<code>PairedRequest</code>](#PairedRequest) | request function for input |
857
858<a name="AsyncRenderFunction"></a>
859
860## AsyncRenderFunction : <code>function</code>
861a function that renders values from a given [Asynchronous] Iterator
862
863**Kind**: global typedef
864
865| Param | Type |
866| --- | --- |
867| program_return; | <code>AsynchronousIterator</code> |
868
869<a name="PushPair"></a>
870
871## PushPair : <code>Array</code>
872an iterator and a paired function to add to it
873
874**Kind**: global typedef
875**Properties**
876
877| Name | Type | Description |
878| --- | --- | --- |
879| 0 | <code>AsynchornousIterator</code> | iterator |
880| 1 | <code>function</code> | function used to add to iterator |
881