Jason
Jason

Reputation: 11363

Implementing generic jquery ajax functions

I have a webapp that has been refactored to use a single global variable in the formats

app.module.function
app.module.submodule.function

I want to refactor my existing generic

function getData(id, type, url, successHandler, rel) {

  var func = window[successHandler]

  $.ajax({
    type : "POST",
    url : url,
    data : {"search" : id, "type" : type, "rel" : rel},
    dataType: "json",
    success : function(data) {
      if (func && typeof func === "function") {
        func(data, id, 0);
      }
    }
  });
}

function to take advantage of the success handlers being passed in. For example, one such success handler is clientRelationshipHandler.

If the handler is defined as

function clientRelationshipHandler(results, id, type) { .. }

then window["clientRelationshipHandler"] returns a function.

However, if I change it to

app.module.submodule.clientRelationshipHandler = function(results, id, type { .. }

both

window["clientRelationshipHandler"]
window["app;.module.submodule.clientRelationshipHandler"]

return undefined and therefore break the generic getData functionality. While using a function that is bound to a specific object, how can I implement a generic success handler for the Ajax query?

Upvotes: 0

Views: 919

Answers (1)

Felix Kling
Felix Kling

Reputation: 816432

I would require the user to pass a function reference to getData, not a string:

function getData(id, type, url, successHandler, rel) { 
  $.ajax({
    type : "POST",
    url : url,
    data : {"search" : id, "type" : type, "rel" : rel},
    dataType: "json",
    success : function(data) {
      if (successHandler && typeof successHandler === "function") {
        successHandler(data, id, 0);
      }
    }
  });
}

// called as
getData(id, type, url, app.module.submodule.clientRelationshipHandler, rel);

Then your function doesn't have to care where the callback is stored, which makes it much more reusable (that's how callbacks are supposed to work).

If you want to preserve this inside the callback, either accept an additional parameter, thisObj and use successHandler.call(thisObj, data, id, 0) or let the user handle this himself (e.g. by using .bind or providing an anonymous function).


An even better solution (IMO), would be to use promises:

function getData(id, type, url, rel) {
  return $.ajax({ // return the promise that `$.ajax` returns
    type : "POST",
    url : url,
    data : {"search" : id, "type" : type, "rel" : rel},
    dataType: "json"
  });
}

which is then called as

getData(id, type, url, rel).then(function(result) {
    app.module.submodule.clientRelationshipHandler(result, id, 0);
});

This completely decouples your code from the callback management and the calling code can handle the response in any way it wants to.

Upvotes: 2

Related Questions