tejacques / crosstab

A utility library for cross-tab communication using localStorage.
Apache License 2.0
364 stars 58 forks source link

Add higher level functionality to API #39

Open tejacques opened 8 years ago

tejacques commented 8 years ago

Currently thinking something along the lines of this:

crosstab({ event, data, destination, callback, timeout })

It could be used like this:

Setup

crosstab.on('PING', function(message, reply) {
  if (message.destination === crosstab.id
    || (!message.destination && crosstab.isMaster())) {
    reply('PONG'); // replies directly to this message
  }
});

It's still a little cumbersome to indicate that this should only handle direct messages, or if it is the master. This could be resolved by having some helper defaults:

crosstab.onDirect(event, fn(message, reply));
crosstab.onMaster(event, fn(message, reply));
crosstab.on(event, fn(message, reply), type=DIRECT | MASTER);

Call

crosstab({
  event: 'PING',
  callback: function(response, err) {
    if(!err) {
      console.log("Received: ", response.data, " from: ", response.origin);
    } else {
      console.log("Error: ", err);
    }
  },
  timeout: 1000
});
crosstab.broadcast(event, data, destination, callback = null, timeout = infinity);
crosstab.broadcast(event, destination, callback = null, timeout = infinity);
crosstab.broadcast(event, callback = null, timeout = infinity);

crosstab.broadcastMaster(event, data, callback = null, timeout = infinity);
crosstab.broadcastMaster(event, callback = null, timeout = infinity);

This will greatly reduce boilerplate and increase ease of use for creating tools based on crosstab.

It also makes it easy to create a Promise wrapper using the callbacks.

tejacques commented 8 years ago

It might make more sense to treat this an an observable (RxJs style) in this form:

crosstab
    // Listen to PINGs
    .subscribe('PING')
    // Only handle messages from master or direct
    .filter(message =>
        crosstab.filters.fromMaster(message)
        || crosstab.filters.directMessage(message))
    // For each PING, reply with a PONG
    .forEach((message) => {
        crosstab.reply(message, 'PONG');
    });

// Send message
crosstab
    // Send PING, and listen for replies
    .broadcast('PING')
    // Set a 1000ms timeout
    .timeout(1000)
    // Only take the first reply
    .take(1)
    // For each reply, print out the response
    .forEach((response => {
        console.log('PING response: ', response);
    });

forEach, filter, and map would take a function in the form of:

function(message, index, observable) {
    // body
}

It's actually probably easier to do this as an RxJs wrapper with something like crosstab.RxWrapper()

So really, there are two wrappers going on here:

crosstab.promiseWrapper() and crosstab.RxWrapper()