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.
importrawr,{transports}from'rawr';// In this instantiation, we can pass in an object to // `methods` that is exposed to our web page (see below)constpeer=rawr({transport: transports.worker(),methods: { calculatePrimes },});functioncalculatePrimes(howMany){// Do something CPU intensive in this thread that// would otherwise be too expensive for our web page ... returnprimes;}importrawr,{transports}from'rawr';constmyWorker=newWorker('/worker.js');constpeer=rawr({transport: transports.worker(myWorker)});// Remote methods are *~automatically available~*constresult=awaitpeer.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.
importrawr,{transports}from'rawr';constsocket=newWebSocket('ws://localhost:8080');socket.onopen=(event)=>{// create the rawr peerconstpeer=rawr({transport: transports.websocket(socket)});};The websocket server could even make arbitrary calls to the client!
socketServer.on('connection',(socket)=>{constpeer=rawr({transport: transports.websocket(socket)});constresult=awaitpeer.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{constresult=awaitpeer.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:
constresult=awaitpeer.methodsExt.processImage({ imageBitmap, stuff },{postMessageOptions: {transfer: [imageBitmap]}});
