Processing $http response in service

后端 未结 12 1629
半阙折子戏
半阙折子戏 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

    As far as caching the response in service is concerned , here's another version that seems more straight forward than what I've seen so far:

    App.factory('dataStorage', function($http) {
         var dataStorage;//storage for cache
    
         return (function() {
             // if dataStorage exists returned cached version
            return dataStorage = dataStorage || $http({
          url: 'your.json',
          method: 'GET',
          cache: true
        }).then(function (response) {
    
                  console.log('if storage don\'t exist : ' + response);
    
                  return response;
                });
    
        })();
    
    });
    

    this service will return either the cached data or $http.get;

     dataStorage.then(function(data) {
         $scope.data = data;
     },function(e){
        console.log('err: ' + e);
     });
    
    0 讨论(0)
  • 2020-11-22 04:28

    Let it be simple. It's as simple as

    1. Return promise in your service(no need to use then in service)
    2. Use then in your controller

    Demo. http://plnkr.co/edit/cbdG5p?p=preview

    var app = angular.module('plunker', []);
    
    app.factory('myService', function($http) {
      return {
        async: function() {
          return $http.get('test.json');  //1. this returns promise
        }
      };
    });
    
    app.controller('MainCtrl', function( myService,$scope) {
      myService.async().then(function(d) { //2. so you can use .then()
        $scope.data = d;
      });
    });
    
    0 讨论(0)
  • 2020-11-22 04:29

    When binding the UI to your array you'll want to make sure you update that same array directly by setting the length to 0 and pushing the data into the array.

    Instead of this (which set a different array reference to data which your UI won't know about):

     myService.async = function() {
        $http.get('test.json')
        .success(function (d) {
          data = d;
        });
      };
    

    try this:

     myService.async = function() {
        $http.get('test.json')
        .success(function (d) {
          data.length = 0;
          for(var i = 0; i < d.length; i++){
            data.push(d[i]);
          }
        });
      };
    

    Here is a fiddle that shows the difference between setting a new array vs emptying and adding to an existing one. I couldn't get your plnkr working but hopefully this works for you!

    0 讨论(0)
  • 2020-11-22 04:32

    I've read http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS allows us to streamline our controller logic by placing a promise directly on the scope, rather than manually handing the resolved value in a success callback.]

    so simply and handy :)

    var app = angular.module('myApp', []);
                app.factory('Data', function($http,$q) {
                    return {
                        getData : function(){
                            var deferred = $q.defer();
                            var promise = $http.get('./largeLoad').success(function (response) {
                                deferred.resolve(response);
                            });
                            // Return the promise to the controller
                            return deferred.promise; 
                        }
                    }
                });
                app.controller('FetchCtrl',function($scope,Data){
                    $scope.items = Data.getData();
                });
    

    Hope this help

    0 讨论(0)
  • 2020-11-22 04:34

    Here is a Plunk that does what you want: http://plnkr.co/edit/TTlbSv?p=preview

    The idea is that you work with promises directly and their "then" functions to manipulate and access the asynchronously returned responses.

    app.factory('myService', function($http) {
      var myService = {
        async: function() {
          // $http returns a promise, which has a then function, which also returns a promise
          var promise = $http.get('test.json').then(function (response) {
            // The then function here is an opportunity to modify the response
            console.log(response);
            // The return value gets picked up by the then in the controller.
            return response.data;
          });
          // Return the promise to the controller
          return promise;
        }
      };
      return myService;
    });
    
    app.controller('MainCtrl', function( myService,$scope) {
      // Call the async method and then do stuff with what is returned inside our own then function
      myService.async().then(function(d) {
        $scope.data = d;
      });
    });
    

    Here is a slightly more complicated version that caches the request so you only make it first time (http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview):

    app.factory('myService', function($http) {
      var promise;
      var myService = {
        async: function() {
          if ( !promise ) {
            // $http returns a promise, which has a then function, which also returns a promise
            promise = $http.get('test.json').then(function (response) {
              // The then function here is an opportunity to modify the response
              console.log(response);
              // The return value gets picked up by the then in the controller.
              return response.data;
            });
          }
          // Return the promise to the controller
          return promise;
        }
      };
      return myService;
    });
    
    app.controller('MainCtrl', function( myService,$scope) {
      $scope.clearData = function() {
        $scope.data = {};
      };
      $scope.getData = function() {
        // Call the async method and then do stuff with what is returned inside our own then function
        myService.async().then(function(d) {
          $scope.data = d;
        });
      };
    });
    
    0 讨论(0)
  • 2020-11-22 04:38

    Because it is asynchronous, the $scope is getting the data before the ajax call is complete.

    You could use $q in your service to create promise and give it back to controller, and controller obtain the result within then() call against promise.

    In your service,

    app.factory('myService', function($http, $q) {
      var deffered = $q.defer();
      var data = [];  
      var myService = {};
    
      myService.async = function() {
        $http.get('test.json')
        .success(function (d) {
          data = d;
          console.log(d);
          deffered.resolve();
        });
        return deffered.promise;
      };
      myService.data = function() { return data; };
    
      return myService;
    });
    

    Then, in your controller:

    app.controller('MainCtrl', function( myService,$scope) {
      myService.async().then(function() {
        $scope.data = myService.data();
      });
    });
    
    0 讨论(0)
提交回复
热议问题