Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to DRY http success and error functions?

Say I have more than 100 requests in my application. It would be cumbersome and time consuming to write as many success and error functions to handle response.

At the moment I do like this:

angular
  .module('mahanApp')
  .service('HttpService', function($http) {
      // Get all  name
      function getNames() {
        return $http.get('/data/names/')
      }

      return {
        getNames: getNames
      }
      .controller('NameController', function NameController(
        HttpService) {
        var ctrl = this;

        // Fetch all templates name;
        HttpService.getNames().then(
          function success(response) {
            ctrl.names = response.data;
          },
          function error(response) {});
      })
  });

As you see, it is a lot of work to write so many callback functions for 100+ requests. I wonder if it is possible to avoid doing so.

There is this questions that suggests to do like the code below.

angular
  .module('mahanApp')
  .service('HttpService', function($http) {

    var success = function(response) {
        return response.data;
      },
      error = function(error) {
        return error.data;
      };

    // Get all  name
    function getNames() {
      return $http.get('/data/names/').then(success, error)
    }

    return {
      getNames: getNames
    }
    .controller('NameController', function NameController(
      HttpService) {
      var ctrl = this;

    })
  });

In the NameController, I used ctrl.names = HttpService.getNames(). But ctrl.names is undefined. How to use the HttpService.getNames() in NameController?

Update:

A few people has commented to resolve the promise.

HttpService.getNames().then(function success(result) {
  ctrl.names = result;
})

It works. However, I still write 100+ functions to resolve the promise.

How to avoid repeating the success and error functions or if possible the whole then() method?

like image 732
mahan Avatar asked Dec 08 '25 18:12

mahan


1 Answers

I will try to sum up the discussion and some ways you can remove duplication:

First of all, your second approach is the right direction to re-using a function in your controllers.

A classical approach would be this:

return {
  getNames: getNames
}
.controller('NameController', function NameController(
  HttpService) {
  var ctrl = this;
  HttpService.getNames().then(function(res) { ctrl.names = res; } );
})

Note that you can even extract this more if all your calls are following the same format, for example you could:

// utility function that loads something into your controller
var load = function(request, ctrl, prop) {
    request.then(function(res) { ctrl[prop] = res; } 
};

// this way you can have many of requests with minimal code
load(HttpService.getNames, ctrl, 'names');
load(HttpService.getBooks, ctrl, 'books');
load(HttpService.getThings, ctrl, 'things');
...

Alternatively, if you can use ES2017 in your project (e.g. your code is transpiled) you can simplify using some of the new features without the need of an additional function:

// Using promise all will assure these are all fetched asynchronously in respect to one another
Promise.all([
    async () => ctrl.names = await HttpService.getNames(),
    async () => ctrl.books = await HttpService.getBooks(),
    async () => ctrl.things = await HttpService.getThings()
]);

Finally, you might actually want to parameterize your request so that you have just one:

// Get all
function getAll(what) {
  return $http.get('/data/' + what).then(success, error)
}

Then you don't need to have a different method for each type, you'll just do:

getAll('names');
getAll('books');
...
like image 142
Ovidiu Dolha Avatar answered Dec 11 '25 10:12

Ovidiu Dolha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!