npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

async-endpoint

v0.0.23

Published

![Async Endpoint Logo](logo.png)

Downloads

199

Readme

Async Endpoint

Async Endpoint Logo

Asynchronous Endpoints, especially when paired with a functional style of programming, provide a sound method of writing programs in JavaScripts that are

- testable
- maintainable
- extendable
- composeable
- easy to reason about
- standard based*

This repository provides a brief intoduction to asynchronous endpoints**, along with a helper library async-endpoint to help make a few things easier.

Table of contents

  • Introduction

    • Synchronous Endpoints
    • Synchronous Iteration
    • Asynchronous Iteration
    • Asynchronous Input
    • Import
    • API

Introduction

Many programming languages use the concept of functions as entry points to transfer control between programs.

Synchronous Endpoints

In javascript, this is as simple as writing a function and calling it:

Example 1

const program = function() {
  console.log("hello world");
};

program();
//logs "hello world"

Taking a queue from functional programming, we can remove the logging side affect from the main program into a separate render function that logs the result retuned from running:

Example 2

const render = console.log;

const program = function() {
  return "hello world";
};

render(program());
//logs "hello world"

Synchronous Iteration

Provided that our render function expects an iterator, We can construct our program with a generator function to yeild multiple results:

Example 3

const render = iterator => {
  //as the result is an iterator
  //we iterate though it and log each subsequent result
  for (const result of iterator) {
    console.log(result);
  }
};

const program = function*() {
  yield "hello";
  yield "world";
};

render(program());
//logs "hello"
//logs "world"

Asynchronous Iteration

When using asynchronous generators, we can await asynchronous APIs, though we must again make sure to modify our fetch function.

Example 4

const render = async asynchronousIterator => {
  //we use the "for await" construct for Asynchronous Iterators
  for await (const result of asynchronousIterator) {
    console.log(result);
  }
};

const program = async function*() {
  yield "fetching...";
  yield await fetch("https://www.google.com");
  yield "results fetched.";
};
render(program());
//logs "fetching..."
//logs result from fetch.
//logs "results fetched."

Asynchronous Input and Interactive Programs

With a few small tricks, asynchronous generators can function as fully interactive programs.

We'll take advantage of the included AsyncArray class to derive a "request" and a "respond" function.

When a program calls request, it will return a promise. This promise will then be fulfilled with the input of the next call to respond.

import { AsyncArray } from "async-endpoint";
const channel = new AsyncArray();
const respond = channel.push.bind(channel),
  request = async ()=>(await channel.next()).value;

By convention, we'll pass two arguments to our asynchronous generator function:

- an _init_ object, which may or may not be ignored
- the aforementioned _request_ function
const program = async function *(init, request){
    ...
}

Finally, we need to connect the respond object to user input. If running in a browser, you could simply attach it to the window object:

window.respond = respond;

Or, if running in node, you can use the included inputConsole function:

import { inputConsole } from "async-endpoint";
inputConsole(respond);

Puttig it all together, we can write an interactive program like this: (Note that instead of defining a render function, we're using the generic renderer from the async-endpoit library instead of writing our own this time).

Example 5

import { AsyncArray, inputConsole, renderer } from "async-endpoint";

const render = renderer();

const program = async function*(init, request) {
  yield "What's your name?";
  yield `Hello ${await request()}`;
};

const channel = new AsyncArray();
const respond = channel.push.bind(channel),
  request = async ()=>(await channel.next()).value;

inputConsole(respond);

render(program(undefined, request)); //the init object will be ignored
//logs "

Related

Renderer for React

Import

There are a few ways to import this into your project.

Pre-Ecmascript Modules

Common JS

The package's main file is a compiled common JS file.

const AsyncEndpoint = require("async-endpoint");
const AsyncEndpoint = require("async-endpoint/common.js"); //also works

This should work with file bundlers, though I haven't had a chance to test it.

import * as AsyncEndpoint from = "async-endpoint/common.js";

Browser

There is also a rollup of the package for the browser, though there are a number of issues getting this to work out of the box. You're probably better off pointing directly to the files in the "js" or "mjs" folders and using a bundler.

    <script src = ".../async-endpoint/browser.js"></script>
    <script>
        alert(typeof window.AsyncEndpoint);
    </script>

Ecmascript Modules

Ecmascript modules are available in two flavors of ecmascript modules:

MJS

In a node application, the "import" keyword can be used to import the package.

    //index.mjs
    import * as AsyncEndpoint from "async-endpoint/mjs";

As of this writing, node requires the the "experimental-modules" and "harmony_async_iteration" flags to be set, but this will change once a the "import" and "asynchronous iterator" features hae landed.

node --experimental-modules --harmony_async_iteration index.mjs

If you wish to avoid experimental the features, use the above common.js module.

JS

In a browser application, the "import" keyword can be used to import the package.

When using ".mjs" files, a server may fail to serve the proper "application/javascript" mime type causing the application to fail. As such, the "js" folder is included.

    <script>
        import * as AsyncEndpoint from "async-endpoint/js/index.js";
        <script>
        alert(typeof window.AsyncEndpoint);
        </script>
    </script>

As of this writing, only Chrome supports the necessary import and asynchronous interation features necessary to get this to work.

To ensure compatibility with other browsers use the above browser.js module. You can also re-bundle either the flow, js, or mjs folders.

//Use
import map from "async-endpoint/js/array-like/map.js";
//rather than 
import {map} from "async-endpoint/js/index.js";

API

Classes

Functions

Typedefs

AsyncArray ⇐ Array

Kind: global class
Extends: Array

new AsyncArray()

An Asynchronous Array

Example

import {AsyncArray} from "async-endpoint";
const input = new AsyncArray();
const main = async()=>{
     setTimeout(()=>{
         input.push("hello world");
     })
     const {value} = await input.next();
     console.log(value);
}
main();
//logs "hello world"

Example

import {AsyncArray} from "async-endpoint";
const input = new AsyncArray();
const main = async()=>{
     setTimeout(()=>{
         input.push("hello");
         input.push("world");
     })
     for await(const value of input){
       console.log(vaue);
     }
}
main();
//logs "hello"
//logs "world"

composePrograms(request, ...programs) ⇒ AsynchornousIterator

composes programs sequentially with a single input

Kind: global function
Returns: AsynchornousIterator - resulting iterator

| Param | Type | Description | | --- | --- | --- | | request | function | request function for input | | ...programs | Program | programs to be composed sequentially |

Example

import {composePrograms, AsyncArray} from "async-endpoint";
import porgram1, program1, program3 from "....js";
const channel = new AsyncArray();
const respond = channel.push.bind(channel),
request = async () => (await channel.next()).value;
const program = composePrograms(request, program1, program2, program3);
window.respond = respond;

creates an iterator whose values are mapped from another(iterator, mapper) ⇒ AsynchornousIterator

Kind: global function
Returns: AsynchornousIterator - resulting iterator

| Param | Type | Description | | --- | --- | --- | | iterator | AsynchornousIterator | iterator to be mapped | | mapper | AsyncTransformer | transformation for individual items |

Example

import {map, continuousOutput},  from "async-endpoint";
let i = 0;
const mapped = map(continuousOutput(()=>i++), (n) => n + 2);
const main = async ()=>{
 for await(item of mapped){
     console.log(item);
 }
}
main();
logs "2"
logs "3"
logs "4"
...

executes a provided funcition for each item of an iterator(iterator, handler) ⇒ undefined

Kind: global function

| Param | Type | Description | | --- | --- | --- | | iterator | AsynchornousIterator | iterator | | handler | AsyncTransformer | provided function |

Example

import {forEach, continuousOutput},  from "async-endpoint";
let i = 0;
forEach(continuousOutput(()=>i++, console.log));
main();
logs "2"
logs "3"
logs "4"
...

filter(iterator, filterer) ⇒ AsynchornousIterator

creates an iterator whose values are filtered from another

Kind: global function
Returns: AsynchornousIterator - filtered iterator

| Param | Type | Description | | --- | --- | --- | | iterator | AsynchornousIterator | iterator to be filtered | | filterer | function | boolean filtering function |

Example

import {filter, continuousOutput} from "async-endpoint";
let i = 0;
const filtered =filter(continuousOutput(()=>i++),  (n)=>n%2);
const main = async ()=>{
 for await(item of filtered){
     console.log(item);
 }
}
main();
logs "1"
logs "3"
logs "5"

reduce(iterator, reducer, [inital], [condition], [resetInitial]) ⇒ AsynchornousIterator

creates an iterator whose values are reduced from another

Kind: global function
Returns: AsynchornousIterator - reduced iterator

| Param | Type | Default | Description | | --- | --- | --- | --- | | iterator | AsynchornousIterator | | iterator to be reduced | | reducer | function | | reducing function | | [inital] | * | | initial object to reduce into | | [condition] | function | (item, initial) => false | boolean filtering function indicating when to start new reduction phase | | [resetInitial] | function | ()=>initial | method to reset/replace initial reduction object |

Example

import {reduce, continuousOutput} from "async-endpoint";
let i = 0;
const reduced = reduce(continuousOutput(()=>i++) , (previous, current)=>previous.push(current),[], (x)=!(x%5), ()=>([]));
const main = async ()=>{
 for await(item of reduced){
     console.log(item);
 }
}
main();
logs "[0]"
logs "[1, 2, 3, 4, 5]"
 ...

reduceRight(iterator, reducer, [inital], [condition], [resetInitial]) ⇒ AsynchornousIterator

creates an iterator whose values are reduced from another

Kind: global function
Returns: AsynchornousIterator - reduced iterator

| Param | Type | Default | Description | | --- | --- | --- | --- | | iterator | AsynchornousIterator | | iterator to be reduced | | reducer | function | | reducing function | | [inital] | * | | initial object to reduce into | | [condition] | function | (item, initial) => false | boolean filtering function indicating when to start new reduction phase | | [resetInitial] | function | ()=>initial | method to reset/replace initial reduction object |

Example

import {reduce, continuousOutput} from "async-endpoint";
let i = 0;
const reduced = reduce(continuousOutput(()=>i++) , (previous, current)=>previous.push(current),[], (x)=!(x%5), ()=>([]));
const main = async ()=>{
 for await(item of reduced){
     console.log(item);
 }
}
main();
logs "[0]"
logs "[1, 2, 3, 4, 5]"
 ...

pause(milliseconds, value) ⇒ Promise

returns a resolved promise after a given amount of time useful for pausing asynchronous programs

Kind: global function
Returns: Promise - promise fulfilled with value

| Param | Type | Description | | --- | --- | --- | | milliseconds | Number | time to pause | | value | * | optional returned value |

Example

import {pause} from "async-endopint.js";
const main = async ()=>{
 console.log("hello");
 await pause(1000);
 console.log("goodbye");
}
main();
//logs "hello"
//logs "goodbye" (after 1 second)

composeAsyncTransformer(last, first) ⇒ AsyncTransformer

composes two asynchoronous transformers

Kind: global function
Returns: AsyncTransformer - asynchonous compositon of current and pre

| Param | Type | Description | | --- | --- | --- | | last | AsyncTransformer | transformer to apply last | | first | AsyncTransformer | transformer to apply first |

Example

import {composeAsyncTransformer} from "async-endopint.js";
const t1 = async (x)=>`<${x}>`;
const t2 = async (x)=>`[${x}]`;
const t = composeAsyncTransformer(t1, t2);
t("hello").then(console.log);
//logs "<[hello]>"

createQueue(...initial) ⇒ PushPair

create a queue iterator

Kind: global function
Returns: PushPair - queue and push function

| Param | Type | Description | | --- | --- | --- | | ...initial | * | initial items in queue |

Example

import {createQueue, renderer, renderer as createPassThrough} from "async-endpoint";
import porgram1, program1, program3 from "....js";
const [queue, push] = createQueue();
const passthrough = createPassThrough(push);
passthrough(porgram1(), program2(), program3());
const render = renderer();
render(queue);

createStack(...initial) ⇒ PushPair

create a stack iterator

Kind: global function
Returns: PushPair - stack and push function

| Param | Type | Description | | --- | --- | --- | | ...initial | * | initial items on stack |

Example

import {createStack, renderer, renderer as createPassThrough} from "async-endpoint";
import porgram1, program1, program3 from "....js";
const [stack, push] = createStack();
const passthrough = createPassThrough(push);
passthrough(porgram1(), program2(), program3());
const render = renderer();
render(stack);

createProgramQueue() ⇒ PushPair

identity program that outputs what ever is input Like "queue", but accepts program as input

Kind: global function
Returns: PushPair - iterator and push function
Example

import {createProgramQueue, renderer} from "async-endpoint";
import porgram1, program1, program3 from "....js";
const [queue, push] = createProgramQueue();
push(porgram1(), program2(), program3());
const render = renderer();
render(queue);

createProgramStack() ⇒ PushPair

identity program that outputs what ever is input Like "queue", but accepts program as input

Kind: global function
Returns: PushPair - iterator and push function
Example

import {createProgramStack, renderer} from "async-endpoint";
import porgram1, program1, program3 from "....js";
const [stack, push] = createProgramStack();
push(porgram1(), program2(), program3());
const render = renderer();
render(stack);

take(iterator, num, [skip]) ⇒ Promise.<Array>

extract items from iterator as array

Kind: global function
Returns: Promise.<Array> - stack and push function

| Param | Type | Default | Description | | --- | --- | --- | --- | | iterator | AsynchronousIterator | | iterator from which to take | | num | Number | | number of items to take from iterator | | [skip] | Number | 0 | number of items to skip before taking |

Example

import {take, continuousOutput} from "async-endpoint";
let i = 0;
take(continuousOutput(()=>i++), 3,1).then(taken=>console.log(taken));
//logs "[1,2,3]"

takeWhile(iterator, accept, [skip]) ⇒ Promise.<Array>

extract first set of items that match a given condition as an array

Kind: global function
Returns: Promise.<Array> - stack and push function

| Param | Type | Default | Description | | --- | --- | --- | --- | | iterator | AsynchronousIterator | | iterator from which to take | | accept | function | | boolean filtering function indicating whether to allow item | | [skip] | Number | 0 | number of items to skip before taking |

Example

import {takeWhile, continuousOutput} from "async-endpoint";
let i = 0;
takeWhile(continuousOutput(()=>i++), x  => x < 5, 2).then(taken=>console.log(taken));
//logs "[2,3,4]"

identity([delay], request) ⇒ AsynchronousIterator

program that outputs what ever is put throught

Kind: global function
Returns: AsynchronousIterator - resulting iterator

| Param | Type | Default | Description | | --- | --- | --- | --- | | [delay] | * | 0 | delay between sending output | | request | PairedRequest | | request function for input |

Example

import {identity, renderer, AsyncArray} from "async-endpoint";
const channel = new AsyncArray();
const respond = channel.push.bind(channel),
request = async () => (await channel.next()).value;
identity(undefined, request);
window.respond = respond

continuousOutput([sample]) ⇒ AsynchronousIterator

program that takes no input and contiuously outputs result of calling function

Kind: global function
Returns: AsynchronousIterator - resulting iterator

| Param | Type | Default | Description | | --- | --- | --- | --- | | [sample] | * | ()=>{} | function whose result to output |

Example

import {continuousOutput, renderer} from "async-endpoint";
const render = renderer();
render(continuousOutput(()=>"hello"))
logs "hello" (continously)
...

renderer([...targets]) ⇒ AsyncRenderFunction

creates a render function that renders yeilded results from programs to any number of target functions. If no targets are given, objects will be rendered using "console.log" Can be used as a "passthrough" (see "createQueue" example)

Kind: global function
Returns: AsyncRenderFunction - asychronous render function

| Param | Type | Description | | --- | --- | --- | | [...targets] | function | request function for input |

Example

import {renderer, continuousOutput} from "async-input.js";
const render = renderer();
render(continuousOutput);
//logs "0"
//logs "1"
...

tee(...programs) ⇒ AsyncRenderFunction

creates a render function whos's values are teed on to given It may be advantageous to use this along side a programQueue

Kind: global function
Returns: AsyncRenderFunction - asychronous render function

| Param | Type | Description | | --- | --- | --- | | ...programs | Program | programs to be sent values |

Example

import {tee, continousOutput, renderer} from "async-endpoint";
import porgram1, program1, program3 from "....js";
const instance1 = program1();
const instance2 = program2();
const instance3 = program3();
const render = renderer();
render(instance1, instance2, instance3)
const renderTee = tee(porgram1, program1, program3)
renderTee(continousOutput())

inputConsole(respond)

send input typed into console to a PairedRespond function

Kind: global function

| Param | Type | Description | | --- | --- | --- | | respond | PairedRespond | request function for input |

Example

import {identity, AsyncArray, renderer} from "async-endpoint";
import inputConsole from "async-endpoint/input/console";
const channel = new AsyncArray();
const respond = channel.push.bind(channel),
request = async () => (await channel.next()).value;
const render = renderer();
render(identity(undefined, request))
inputConsole(respond);

inputPipe(respond)

send input piped to console to a PairedRespond function

Kind: global function

| Param | Type | Description | | --- | --- | --- | | respond | PairedRespond | request function for input |

Example

import {identity, renderer, AsyncArray} from "async-endpoint";
import inputPipe from "async-endpoint/input/pipe";
const channel = new AsyncArray();
const respond = channel.push.bind(channel),
request = async () => (await channel.next()).value;
const render = renderer();
render(identity(undefined, request))
inputPipe(respond);

PairedRequest ⇒ Promise.<*>

a function that receives it's response from a paired PairedRespond function

Kind: global typedef
Returns: Promise.<*> - response from respond reunction

PairedRespond : function

a function that sends it's input to a paired PairedRequest function

Kind: global typedef

| Param | Type | Description | | --- | --- | --- | | response | * | response for request function |

AsyncTransformer ⇒ *

stateless asynchronous function that transforms input without side effects

Kind: global typedef
Returns: * - transformed input

| Param | Type | Description | | --- | --- | --- | | input | * | input |

Program ⇒ AsynchronousIterator

an iteractive program

Kind: global typedef
Returns: AsynchronousIterator - asynchronous iterator result

| Param | Type | Description | | --- | --- | --- | | init | * | | | request | PairedRequest | request function for input |

AsyncRenderFunction : function

a function that renders values from a given [Asynchronous] Iterator

Kind: global typedef

| Param | Type | | --- | --- | | program_return; | AsynchronousIterator |

~~PushPair : Array~~

Deprecated

an iterator and a paired function to add to it

Kind: global typedef
Properties

| Name | Type | Description | | --- | --- | --- | | 0 | AsynchornousIterator | iterator | | 1 | function | function used to add to iterator |