Skip to content

Instantly share code, notes, and snippets.

@mdbarr
Created February 28, 2019 15:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdbarr/1a416707f5fd7e763110542ab35ce7e4 to your computer and use it in GitHub Desktop.
Save mdbarr/1a416707f5fd7e763110542ab35ce7e4 to your computer and use it in GitHub Desktop.
Provider Model

Provider Model with Event Bus

The idea behind the provider model is to create back-end agnostic code that depends on a provider plugin to connect and and communicate with the main service. Plugins provide communication layer so that the application itself can deal only with idealized data and straight-forward verbal actions. Decoupling the communication layer from the front-end code allows for a cleaner and more easily testable application.

This works especially well when using the notion of a central event bus with font-end components publishing via the bus requests for data and user actions and subscribe to relevant updates. The provider in turn subscribes to the actions it can specifically handle, communicates this to the back-end and then publishes the result on the event bus for any listening components.

There are a few addition gains that make this ideal for debugging, integration and end to end testing. Since the provider is only a subscriber to specific events and not the sole consumer, more than one provider can be used by the application without changing any code or needing to proxy messages between back-end servers, components or connections.

This enable both multiple providers when the backend requires multiple and distinct connections as well as the ability to include a debugging, logging, or replay provider along side any real back-end providers.

Providers can also be set up as Node.js modules so that they can be independently developed and maintained, and then included in the front-end application using semantic versioning to ensure the right version in included.

Vue's plugin architecture makes this especially simple. Below is a bit of not-quite-psuedo code to illustrate how this works in practice.

// Event Bus
Vue.prototype.$events = new Vue({ 
  methods: {                                                                               
    $send(object) {
      this.$emit(constants.message.send, object);                                          
    }                                                                                      
  }
});

// Providers
ProviderWebsocket.install = function (Vue, options) {
  const capabilities = {
      authentication: true,
      graphics: true,
      somethingCool: true
  };

  const ws = new WebSocket('ws://localhost:8082');
  
  // Message received
  ws.on('message', function(message) {
      Vue.prototye.$events.$send(message.type, message.data);
  });
  
  Vue.prototype.$events.$on('request', function(message) {
      ws.send(message.data);
  });
  
  Vue.prototype.$events.$on('capabilities', function(message) {
      Vue.prototype.$events.$send('capable', capabilities);
  });
  
  Vue.prototype.$events.on('init', {
    ws.connect();
  });
};

ProviderLogger.install = function(Vue, options) {
  Vue.prototype.$events.$on('request', function(message) {
   console.log('REQUEST', message);
  });
  
  Vue.prototype.$events.$on('data', function(message) {
    console.log('DATA', message);
  });

  Vue.prototype.$events.on('init', {
    console.log('Logger listening on event bus');
  });
};

ProviderRest.install = function(Vue, options) {
  const capabilities = {
    getData: true
  };

  Vue.prototype.$events.$on('get', function(message) {
   axios.get(message.url).
     then(function(response) {
      Vue.prototype.$events.$send(response.type, response.data);
     });
  });
  
  Vue.prototype.$events.$on('capabilities', function(message) {
      Vue.prototype.$events.$send('capable', capabilities);
  });
};

// Include all providers simultaneously as plugins
Vue.use(ProviderWebsocket);
Vue.use(ProviderRest);
Vue.use(ProviderLogger);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment