Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a JavaScript API wrapper

Can anyone suggest a pattern that can be used for writing a JavaScript API wrapper, where there is no shared code between multiple implementations? The idea is to provide the client consumer with a single wrapping API for one of many possible APIs determined at runtime. APIs calls could be to objects/libraries already in the app environment, or web service calls.

The following bits of pseudo-code are two approaches I've considered:

Monolithic Solution

var apiWrapper = {
      init: function() {
          // *runtime* context of which API to call
          this.context = App.getContext(); 
      },
      getName: function() {
           switch(context) {
             case a:
               return a.getDeviceName() // real api call
             case b:
               return b.deviceName // real api call
             etc...
           }
      // More methods ...
    }
}

Pros: Can maintain a consistent API for the library consumers.

Cons: Will result in a huge monolithic library, difficult to maintain.

Module Solution

init.js

// set apiWrapper to the correct implementation determined at runtime
require([App.getContext()], function(api) {
  var apiWrapper = api;
});

module_a.js

// Implementation for API A
define(function() {
  var module = {
      getName: function() {
         return deviceA.getDeviceName();
       }
  };
  return module;
});

module_b.js

// Implementation for API B
define(function() {
  var module = {
      getName: function() {
         // could also potentially be a web service call
         return deviceB.getName;
       }
  };
  return module;
});

Pros: More maintainable.

Cons: Developers need to take care that API remains consistent. Not particularly DRY.

This would be a case where something along the lines of an Interface would be useful, but as far as I'm aware there's no way to enforce a contract in Js.

Is there a best practice approach for this kind of problem?

like image 485
Bayard Randel Avatar asked Feb 13 '12 02:02

Bayard Randel


Video Answer


2 Answers

what a coincidence, someone is out there doing what i am also doing! recently, i have been delving into JS application patterns and i am exploring the modular pattern.

i started out with this artice which has a lot of links that refer to other JS developers.

it would be better to go modular:

  • mainly to avoid dependencies between two parts of a website
  • though one could depend on the other, they are "loosely coupled".
  • in order to build a site, it should work without breaking when you tear it apart
  • also, you need to test out parts individually without using everything else
  • easily swap out underlying libraries (jQuery, dojo, mootools etc.) without actually affecting the existing modules (since you are building our own API)
  • in cases you need to change/upgrade your API (or when you change the underlying library), you only touch the API "backing" and not the API nor re-code the parts that are using it

here are links i have been through (vids mostly) that convey what the modular approach is all about and why use it:

  • by nicholas zakas - how to organize the API, libraries and modules
  • by addi osmani - how and why modules
  • by Michael Mahemoff - automatic module event (shout/listen) registration
like image 119
Joseph Avatar answered Oct 06 '22 11:10

Joseph


Second approach is better because it is modular and you or a third person can easily extend it to incorporate other services. Point of "API remaining consistent" is not so valid because proper unit-tests you keep things consistent.

Second approach is also future proof because you don't know what unimaginable things you may have to do to implement say getName for service C, in that case it is better to have a separate module_c.js with all complications instead of spaghetti code in monolithic single module.

Need for real-interface IMO is not so important, a documented interface with unit-tests is enough.

like image 39
Anurag Uniyal Avatar answered Oct 06 '22 10:10

Anurag Uniyal