The @statewalker/webrun-ports
JavaScript library offers a set of utilities designed for handling asynchronous calls and managing the exchange of data streams through MessageChannel
Ports.
This library enables the initiation of calls and receipt of responses across bidirectional channels, utilizing MessagePort
instances provided by MessageChannel
. The methods in this library guarantee that each call is either processed or rejected, ensuring no indefinite hangs. In cases where the peer fails to handle the request appropriately or if the request exceeds a specified time limit, a timeout exception is raised on the caller's side.
In addition to these fundamental calling functionalities, the library includes an implementation of asynchronous iterators. Clients can send, and servers can handle, asynchronous iterators, serving as a foundation for bidirectional communication using AsyncIterators
.
High-level methods to perform individual calls over MessagePort
instances:
- callPort - implements asynchronious port calls with timeouts; (see the
listenPort
method) - listenPort - listens the specified port and delegates calls to the registered handler; the methods are handled asynchronously and results delivered to the caller (see the
callPort
method)
Example: call a remote peer and recieve the result
const channel = new MessageChannel();
channel.port1.start();
channel.port2.start();
const close = listenPort(channel.port1, async (params) => {
return {
message: "Hello World!",
params
}
});
try {
const result = await callPort(channel.port2, { foo: "bar" });
console.log(result);
// Output:
// { message: 'Hello World!', params: { foo: 'bar' } }
} finally {
close();
}
Hig-level methods to call AsyncGenerator
functions with AsyncIterator
as parameters:
- callBidi - This method calls the peer handler over a port with a stream of input values and it returns the stream of resulting values
- listenBidi - Listens for entering requests and delegates calls to the given method to handle input streams; the resulting stream of values is retuned by the handler method is returned to the caller over the same port.
Example:
const channel = new MessageChannel();
channel.port1.start();
channel.port2.start();
// The "server-side" handler transforming input stream
// to a sequence of output values:
async function* handler(input, params) {
for await (let value of input) {
yield value.toUpperCase();
}
}
// Registration of the server-side handler:
const close = listenBidi(channel.port1, handler);
try {
// Input values.
// It could be an AsyncIterator instead.
const input = ["Hello", "World"];
const params = { foo: 'Bar' };
for await (let value of callBidi(
channel.port2,
input,
params
)) {
console.log('* ', value);
}
} finally {
close();
}
// Output:
// * HELLO
// * WORLD
AsyncIterator
s over MessagePort
s:
- recieve - transforms a sequence of calls to the specified port to an AsyncIterator; Internally uses the
recieveIterator
method. On the other side the thesend
method used to send an iterator. - send - sends the specified async iterator over the specified port; Internally uses the
sendIterator
method. On the other side therecieve
method handles calls.
Utility methods, without dependencies on MessagePort
s:
- errors - contains serializeError/deserializeError methods transforming exceptions in JSON objects and restoring them back as Error instances
- recieveIterator - an adaptor method allowing to transform a sequence of calls to the
onMessage
method to an async iterator - sendIterator - an utility method transforming an iterator to a sequence of calls to the registered handler.
Other files:
index.j
the main entry point for the library; re-exports all defined methods
This method calls the peer handler over a port with a stream of input values and it returns the stream of resulting values.
Parameters:
port
- aMessagePort
instance used to transmit the messagesinput
- The input to send to the peer; anAsyncIterator
instance.args
- The arguments object containing call parameters.args.options
- The call options like:bidiTimeout
- The timeout of the stream to recieve; by default it is 2147483647 (max integer).timeout
- The timeout of invidual calls (1000 ms by default); used to send each individual stream value.
args.params
- Additional call parameters used by peers to handle calls; it could contain some parameters like method name; the peer side will recieve in parameters the generatedchannelName
value.
Returns an AsyncIterator
that yields the resulting values retured by the peer.
This function calls the specified port with the given payload.
port
: The name of the port to call.payload
: The payload to send to the port. Returns a promise that resolves when the port call is complete.
This file contains the following methods:
This method takes an error object and transforms it into a JSON object.
This method takes a JSON object representing an error and restores it back as an Error instance.
Listens for entering requests and delegates calls to the given method to handle input streams; the resulting stream of values is retuned by the handler method is returned to the caller over the same port.
Parameters:
port
- aMessagePort
sending/recieving messagesaction
- anAsyncGenerator
instance recieving anAsyncIterator
with input values and yielding a stream of restuls returned to the calleraccept
- the function allowing to accept/reject the initial call based on recieved parameters.
It returns a method allowing to remove the registered call handler.
This function listens to the specified port and delegates calls to the registered handler. The methods are handled asynchronously and results are delivered to the caller.
port
: The name of the port to listen to.handler
: The handler function that will be called when a method is invoked on the port.
This function transforms a sequence of received messages from a specified port into an asynchronous iterator.
port
: The port number to listen to.options
: Additional options for receiving messages (optional).
Returns an asynchronous generator that yields received messages.
Sends data from an async iterator to a specified port.
port
: The port to send the data to.output
: The data to send.options
: Additional options for sending the data.
Returns a promise that resolves when the data is received.
Sends values from an iterator to a specified function.
send
: The function sending values to the remote handlers.it
: The iterator to send values from.
Returns a promise that resolves when the iterator is fully consumed.