[update: keeping this around for posterity, but we ultimately went to a pub/sub pattern, using Amplify.js. Amplify isn't strictly necessary to implement pub/sub, but it has some nice features and syntax]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.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:Make calls to ta.api methods and supply success and error handlers as needed. I.e. you would define them in the methods that ultimately call the REST API.Make void calls to ta.api, but the success and error handlers are supplied in the ta.callbacks object.You can still continue to make calls to the REST service with whatever other arbitrary methods you choose.*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.
JavaScript API for REST
javascript;jquery;ajax;api;rest