Processing $http response in service

后端 未结 12 1689
半阙折子戏
半阙折子戏 2020-11-22 03:36

I recently posted a detailed description of the issue I am facing here at SO. As I couldn\'t send an actual $http request, I used timeout to simulate asynchrono

12条回答
  •  攒了一身酷
    2020-11-22 04:25

    I really don't like the fact that, because of the "promise" way of doing things, the consumer of the service that uses $http has to "know" about how to unpack the response.

    I just want to call something and get the data out, similar to the old $scope.items = Data.getData(); way, which is now deprecated.

    I tried for a while and didn't come up with a perfect solution, but here's my best shot (Plunker). It may be useful to someone.

    app.factory('myService', function($http) {
      var _data;  // cache data rather than promise
      var myService = {};
    
      myService.getData = function(obj) { 
        if(!_data) {
          $http.get('test.json').then(function(result){
            _data = result.data;
            console.log(_data);  // prove that it executes once
            angular.extend(obj, _data);
          }); 
        } else {  
          angular.extend(obj, _data);
        }
      };
    
      return myService;
    }); 
    

    Then controller:

    app.controller('MainCtrl', function( myService,$scope) {
      $scope.clearData = function() {
        $scope.data = Object.create(null);
      };
      $scope.getData = function() {
        $scope.clearData();  // also important: need to prepare input to getData as an object
        myService.getData($scope.data); // **important bit** pass in object you want to augment
      };
    });
    

    Flaws I can already spot are

    • You have to pass in the object which you want the data added to, which isn't an intuitive or common pattern in Angular
    • getData can only accept the obj parameter in the form of an object (although it could also accept an array), which won't be a problem for many applications, but it's a sore limitation
    • You have to prepare the input object $scope.data with = {} to make it an object (essentially what $scope.clearData() does above), or = [] for an array, or it won't work (we're already having to assume something about what data is coming). I tried to do this preparation step IN getData, but no luck.

    Nevertheless, it provides a pattern which removes controller "promise unwrap" boilerplate, and might be useful in cases when you want to use certain data obtained from $http in more than one place while keeping it DRY.

提交回复
热议问题