0.0.8 • Published 4 years ago

awaited.io v0.0.8

Weekly downloads
17
License
BSD-3-Clause
Repository
github
Last release
4 years ago

awaited.io

A minimalistic socket.io RPC using Promises and async/await

Index

Install

npm install awaited.io

Usage - server

Let's make a simple server that exposes an API to operate the an ES6 Map object.

The Map will be exposed to our API functions via a shared context so all the clients connecting with our RPC server will access the same Map instance.

const AwaitedIO = require('awaited.io');
const SocketIO  = require('socket.io');

const api   = {}
api.mapHas  = (ctx, key) => ctx.map.has(key);
api.mapGet  = (ctx, key) => ctx.map.get(key);
api.mapSet  = (ctx, key, value) => ctx.map.set(key, value);

const ctx   = {
  map: new Map()
};

const io = new SocketIO().listen(3131);

io.on('connection', socket => {
  const aio = new AwaitedIO(socket, { ctx });

  aio.registerAPI(api);
});

Usage - client

Now let's make a client to connect to our remote API

const AwaitedIO = require('awaited.io');
const ClientIO  = require('socket.io-client');

async function main () {
  const socket    = new ClientIO('http://localhost:3131');
  const aioClient = new AwaitedIO(socket);

  const remote = await aioClient.update();

  await remote.mapSet('foo', 'bar');
  console.log('-- response:', await remote.mapHas('foo'));
  // -- response: true
  console.log('-- response:', await remote.mapGet('foo'));
  // -- response: bar
}

main();

That's it ;)

Registering functions

To register functions to be exposed to the client side you can use the register and the registerAPI methods.

Registered functions that return a Promise will be awaited until the promise is resolved or rejected to send its response to the client side.

register : function (name, func) - Registers a function to be exposed.

registerAPI : function (apiObj) - Registers a set of functions.

Examples:

Register a single method

aio.register('add', (ctx, a, b) => a+b);

Register multiple methods at once

aio.registerAPI({
  sqrt        : (ctx, num) => Math.sqrt(num),
  delaySqrt   : (ctx, secs, num) => {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(Math.sqrt(num))
      }, secs * 1000)
    });
  }
});

Calling functions from the client

There are two ways of doing this.

Use the call method:

call : function (name, args...) - Calls the method name on the server side passing it args... as arguments.

let result = await aioClient.call('sqrt', 4);

The other one is first call the update method wich will map the exposed function in the remote object of the instance and also return it:

const remote = aioClient.update();

let result = await aioClient.remote.sqrt(4);
// =
let result = await remote.sqrt(4);

All remote function wrappers return promise so this is the same as the code above:

iaoClient.update()
.then((remote) => {
  return aioClient.remote.sqrt(4);
})
.then((res) => {
  let result = res;
});

Middleware

Awaited.io allows you to set middleware functions on the server side. The middleware chain is executed in the same order it's declared.

When you register a function to be exposed to the client side it is internally attached to the middleware chain, so if you want your middleware to be executed before the response is sent to the client make sure you atach it before registering your exposed functions.

The middleware functions MUST be async or return a Promise.

These functions get three arguments:

next : function (err) - This function MUST ALWAYS be called somewhere in the middleware function. If an error is passed the execution of the middleware chain will stop and the error will be passed to the client side which will reject the Promise returned by the remote function call.

ctx : object - The shared context

msg : object - The message passed from the client, which will look like:

{
  id    : 'dc60f70e-bcb8-4b7c-bf1b-9da460733c8a',
  name  : 'mapSet',
  args  : ['foo', 'bar']
}

Example:

Middleware to log the API calls and the time taken to respond

aio.use(async (next, ctx, msg) => {
  const now = new Date(); 

  await next(); // Await for the middleware chain to end execution

  const ms = new Date() - now;
  console.log(`-- ${msg.id} - ${msg.name} - ${ms}ms`);
});

Errors

If the debug option is set to false, which is the default, errors on your functions will be printed to the console. Otherwise will be sent to the client and thrown there.

The client is a server and the server is a client

As you may have noticed the same Awaited.io code is used on the server and the client so you can register functions on the client side and call them from the server. The sky is the limit ;)

Examples

By now there is only one example which is used as a test for all the module functions. It is well commented and I recomend you to read it if you want to know a little more how Awaited.io works.

Also the module code is less than 140 lines of code and is well commented too.

Coffee contributions accepted

As you may know developers fuel is coffee.

Now that Github enabled BAT Rewards, if you are using Brave Browser and feel that I deserve some coffee you can send me a tip or set a monthly contribution.

If you are still not using Brave Browser, you can download it using this link and I will get some BAT to buy more coffee ;)

Brave Browser is a superfast browser based in Chrome with integrated ad blocking and anti-tracking features. Give it a try!

License

Copyright 2017 Albert Calbet Martinez

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0.0.8

4 years ago

0.0.7

7 years ago

0.0.6

7 years ago

0.0.5

7 years ago

0.0.4

7 years ago

0.0.3

7 years ago

0.0.2

7 years ago

0.0.1

7 years ago