Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have a REST API, which naturally you can just use HTTP calls (mainly Ajax) in order to send and receive data. I am building a layer of abstraction on top of the raw REST API for JavaScript Developers. I already use jQuery in the project, so I am using $.ajax(). I feel like I have arrived at a good pattern, but I'm not absolutely certain. Here's my code:

var ta = ta || {};

$.ajaxSetup({
  cache: false
});

ta.api = {
  heartbeat: function(successCallback, errorCallback) {
    var callType = "heartbeat";
    // if no custom handlers are provided, wire up the default callbacks or blank callback methods
    successCallback = ta.utils.setDefaultIfNeeded(successCallback, ta.callbacks[callType].success);
    errorCallback = ta.utils.setDefaultIfNeeded(errorCallback, ta.callbacks[callType].error);

    var url = '/rs/heartbeat';

    $.ajax({
      url: url,
      success: function(data) {
        successCallback(data);
      },
      error: function(xhr) {
        errorCallback(xhr);
      }
    });
  },
  version: function(successCallback, errorCallback) {
    var callType = "version";
    // if no custom handlers are provided, wire up the default callbacks or blank callback methods
    successCallback = ta.utils.setDefaultIfNeeded(successCallback, ta.callbacks[callType].success);
    errorCallback = ta.utils.setDefaultIfNeeded(errorCallback, ta.callbacks[callType].error);

    var url = '/rs/version';

    $.ajax({
      url: url,
      success: function(data) {
        successCallback(data);
      },
      error: function(xhr) {
        errorCallback(xhr);
      }
    });
  }
}

ta.utils = {
  setDefaultIfNeeded: function (providedHandler, defaultHandler) {
    var checkedHandler = providedHandler;
    if (typeof (providedHandler !== "undefined")) {
      if (typeof (providedHandler) !== "function") {
        if (typeof (defaultHandler) === "function") {
          checkedHandler = defaultHandler;
        } else {
          checkedHandler = function () { /* intentionally empty */ };
        }
      }
    } else {
      checkedHandler = function () {  /* intentionally empty */ };
    }
    return checkedHandler;
  }
};

So, the API can accept success and error handlers on a per-call basis. The "setDefaultIfNeeded" will do a few pieces of logic, but one of those pieces is an optional phase of using handlers from a callback object. So the callback object is optional, but it's a handy place to store and organize callbacks:

ta.callbacks = {
  heartbeat: {
    success: function(data) { console.log(data) },
    error: function(xhr) { console.log(xhr.statusText) }
  },
  version: {
    success: function(data) { console.log(data) },
    error: function(xhr) { console.log(xhr.statusText) }
  }
}

Another addition I plan to make but haven't tested yet is to have the functions return the jqXhr. It's already being made, so why not return it? But I haven't tested that yet so I didn't want to provide sample code that might be broken.

So, there are now a few options for using the API, depending on your needs:

  1. Make calls to ta.api methods and supply success and error handlers as needed. Ie. you would define them in the methods that ultimately call the REST API.
  2. Make void calls to ta.api, but the success and error handlers are supplied in the ta.callbacks object
  3. You can still continue to make calls to the REST service with whatever other arbitrary methods you choose
  4. *planned - define a variable against ta.api which becomes a jqXhr. You then have full access to the XHR and can do with it as you please.

I have a suspicion that some of you will recommend deferred/promises API, and I am not against it. But if I'm being honest, I can't visualize a strong way to encapsulate the various moving parts and have them extremely readable for other devs.

I think this is my first CodeReview question. Be gentle. ;)

share|improve this question
    
Aw, come on. If you're going to downvote, comment why. ;) I don't bite! I'd LIKE to be a valuable member, but I need to know how. I do OK over at StackOverflow. –  Greg Pettit Jun 29 at 19:04
1  
We review real code, not design -- please post the code for your API, and note that you want to focus on the design. Sample code is perfectly fine, but unless that's the code you want reviewed, don't post it. –  QPaysTaxes Jun 29 at 19:11
1  
Welcome to Code Review! We don't review "sample code" as that is off topic and doesn't have the necessary information required for a good review. Please update your question to contain the real code so it doesn't get closed as off topic. –  Hosch250 Jun 29 at 19:13
    
Gotcha! It's real code, though. I mean, there are a few sensible substitutions: "heartbeat" with "someCall" because it doesn't matter to the code that it's called heartbeat instead of someCall. Where does one go for design review? Is there a Design Review site? –  Greg Pettit Jun 29 at 19:24
    
Edited 'n' stuff. Feedback solicited! –  Greg Pettit Jun 30 at 15:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.