Remote Procedure Calls (JSON-RPC) sent over any EventEmitter-based transport. WebWorkers, WebSockets, MQTT, and more!
npm install rawr
Every rawr peer can act as both a client and a server, and make remote method calls in either direction.
For example, we can use methods that belong to a webworker.
import rawr, { transports } from 'rawr';
// In this instantiation, we can pass in an object to
// `methods` that is exposed to our web page (see below)
const peer = rawr({
transport: transports.worker(),
methods: { calculatePrimes },
});
function calculatePrimes(howMany) {
// Do something CPU intensive in this thread that
// would otherwise be too expensive for our web page
...
return primes;
}
import rawr, { transports } from 'rawr';
const myWorker = new Worker('/worker.js');
const peer = rawr({transport: transports.worker(myWorker)});
// Remote methods are *~automatically available~*
const result = await peer.methods.calculatePrimes(349582);
The methods are available to the rawr peer through the magic of Proxies
We could use rawr to make calls to a remote server such as a websocket. Simply use a different transport.
import rawr, { transports } from 'rawr';
const socket = new WebSocket('ws://localhost:8080');
socket.onopen = (event) => {
// create the rawr peer
const peer = rawr({
transport: transports.websocket(socket)
});
};
The websocket server could even make arbitrary calls to the client!
socketServer.on('connection', (socket) => {
const peer = rawr({
transport: transports.websocket(socket)
});
const result = await peer.methods.doSomethingOnClient();
});
Peers can also send each other notifications:
peer.notifiers.saySomething('hello');
Receiving those notifications from another peer is just as simple:
peer.notifications.onsaySomething((words) => {
console.log(words); //hello
});
Transporst are simply EventEmitters that do two things:
They emit (json-rpc) objects on an rpc
topic when receiving data.
transport.emit('rpc', {jsonrpc:'2.0', id: 1, method: 'add', params: [2, 3]});
They send rpc objects out.
transport.send({jsonrpc:'2.0', id: 1, method: 'subtract', params: [5, 4]});
While, websockets, mqtt, and webworkers are common, transports could be built from any form of communication you wish!
if you need to pass configuration specific method invocations, you can uses the methodsExt
property of a rawr instance.
For example, if you want to specify a specific timeout for a method call you can use a configuration object as the last parameter:
try {
const result = await peer.methodsExt.doSomething(a, b, { timeout: 100 });
} catch(e) {
// method took longer than a 100 millseconds
}
This also works for customizaton of the transport. For example, you may want to pass configuration for transferable objects to a webWorker:
const result = await peer.methodsExt.processImage({ imageBitmap, stuff }, {
postMessageOptions: { transfer: [imageBitmap] }
});