promise.rpc
v1.0.4
Published
Promise.RPC is my version of a small footprint RPC library for modern JavaScript, it "just works" in the way we mostly use javascript these days.
Readme
Promise.RPC
Promise.RPC is my version of a small footprint RPC library for modern JavaScript, it "just works" in the way we mostly use javascript these days.
This document is a bit of a stream of conciousness... it's basically a rough draft.
I would consider this version stable for production use, caveats could be around error handling/propgation/timeouts while there are some tests around this, I'm not 100% sure it works the way you would want.
This is protocol agnostic, you can use websockets or TCP/IP streams, or stdin/out... etc.
There's no error recovery, so I wouldn't recommend it for lossy connections like UDP or a physical layer, like over serial connections.
There's a PromiseRPCStream that works well with node.js streams and piping, which is nice.
The basic protocol is constructed like this
const {PromiseRPCProtocol} = require("promise.rpc");
const prpc1 = new PromiseRPCProtocol(handler)The handler is a function that is called when the other side wants to execute something in your context. You can also just pass in an object with functions, and a simple default handler will be used instead, that will call your functions as named.
const prpc1 = new PromiseRPCProtocol({
alert(arg1) { console.log("ALERT", arg1) }
});If you wanted to execute the alert function in the context of prpc1 you'd create another promise.prc protocol object, and then connect them
// create the other end of the connection
const prpc2 = new PromiseRPCProtocol();
// make them talk to each other
prpc1.onDispatch = msg => prpc2.dispatch(msg);
prpc2.onDispatch = msg => prpc1.dispatch(msg);
// call the alert function
prpc2.execute('alert', ["test"]);The execute function calls a function on the remote, but does not setup any promises for the effort so the function result is just ignored. Functions calls are bidirectional, there's no reason you can't add function calls to the second prpc2 object.
If you want to get some data from the first connection you can make an rpc call with the .request function, this will setup a unique identifier for a response slot, this will timeout within 5 seconds, which is fairly short, but worked for most of my examples. A timedout request simply results in a .reject('timeout') there may be a better way to handle this, and I'm open to suggestions. This is a timeout that is only respected on the requesters side, the called side will still expect this request to eventually be fulfilled, and will retain resources (callbacks and such) to this effect. The called side may still fullfil this request, but the callers' side has already rejected the promise and it's just silently ignored.
If you wish to change the timeout, that is on the instance.TIMEOUT variable.
There's a function on the rpc instance called 'randomId', it creates approximately 24 bits of entropy in a random id string. Due to the combination of timeout and other considerations, it should be highly unlikely that you'd have a collision, but ... I coded this in a way to be overrideable, so if you wish to use uuidv4 or something that's more to your liking you can simple set the instance variable to have whatever function you want.
You can obviously broadcast this over whatever channels you want, in one of my early tests I connected to the stdin and stdout, and then used it as a shell for an ssh user, and boom ssh/rpc :D it worked well.
There's a great simple example the the examples directory, runs a websocket server / react based webpage that adds tasks to the servers "single source of truth" which is also broadcasted to the clients. I would also recommend a similar style to building the "api proxy" object in your implementations.
There's a number of tests included that should help you understand the purpose/capabilities of this small module. I wrote this over the years as my personal replacement for substack's dnode, dnode is great but it's a bit "too much" for most of what I want. I loved the "turtles all the way down" mantra, but callback hell was a design paradigm from a decade ago.
