简体   繁体   中英

AngularJS - Best approach for taking data from factory and if not there use http service

In my angularJS application, I have set data received from one controller's ajax and put in factory method to reuse in other controllers. The problem is when user reload page, this factory method is useless.

app.factory('factory', function () { 
    return {
        set: set,
        get: get
    }
});
app.controller ('testController', function ($scope, factory) { 
   if (factory.get('name')) {
        $scope.name= factory.get('name');
    } else {
     $http.get(url).then(function(res) {
        $scope.name= res.name;
        factory.set('name', res.name);
        });
    }
});

What is the best way to retrieve this check in factory method which will get value from factory, if not there take from http service and in controller common code needs handle these two cases that done factory method?

Here when data taken from http service it returns promise otherwise plain value.

First create a factory :

app.factory('factoryName', ['$http','$q', function($http,$q) {
    return {
        getData : function(arg1,arg2) {
            return $http.get('/api-url'+arg1+'/'+arg2)
              .then(function(response) {
                if (typeof response.data === 'object') {
                    return response.data;
                } else {
                    return $q.reject(response.data);
                }

            }, function(response) {
                return $q.reject(response.data);
            });
         }
       }
     }])

Provide every api details in this factory, so you can use this factory in multiple controllers.

In Controller inject the factory (factoryName) as a dependency.

app.controller ('testController',['$scope', 'factoryName', function($scope, factoryName) {       
     factoryName.getData(arg1,arg2,...)
      .then(function(data) {
        console.log(data);
      }, function(error){
        console.log(error);
      });
 }]);

For detailed description :- http://sauceio.com/index.php/2014/07/angularjs-data-models-http-vs-resource-vs-restangular/

This code will fetch data from server if the 'cachedResult' variable is not set, otherwise return a promise from the stored variable.

app.factory('factoryName', ['$http','$q', function($http,$q) {
        var cahedResult = null;

        var myMethod = function(args) {
            var deferred = $q.defer(); 

            if (cahedResult){
                deferred.resolve({ data : cahedResult });
                return deferred.promise;
            }

            $http.get(....).then(function(response){
                cahedResult =  response.data;
                deferred.resolve({ data : cahedResult });        
            },function(error){
                deferred.reject('error');  
            });
         }
       };

        return {
            myMethod : myMethod
        }
    ])

But you could also store the data in local storage or in a cookie when the first controller fetch the info so that it's available even if user refresh the browser.

Directly return a promise from your factory

app.factory('factoryName', function () {
    var connectionurl ='...';   //Sample: http://localhost:59526/Services.svc
    return {
        connectionurl : connectionurl ,

        methodName: function (parameters) {
            $http({
                method: 'GET',
                url: connectionurl + 'servicemethod_name'
            })}
}

    }
});

In this case your controller will look like

app.controller ('testController', function ($scope, factoryName) { 
   factoryName.methodName(parameters).then(function(){
   $scope.variable=response.data;
   /*binding your result to scope object*/
   }, function() {
   /*what happens when error occurs**/
   });
});

Other way is directly bind to a scope object through success callback function

app.factory('factoryName', function () {
    var connectionurl ='...';   //Sample: http://localhost:59526/Services.svc
    return {
        connectionurl : connectionurl ,
        methodName: function (parameters,successcallback) {
            $http({
                method: 'GET',
                url: connectionurl + 'servicemethod_name'
            }).success(function (data, status, headers, config) {
                successcallback(data);
            })
           .error(function (data, status, headers, config) {
               $log.warn(data, status, headers, config);
           });
        }
    }
});

In this case your controller will look like

app.controller ('testController', function ($scope, factoryName) { 

   factoryName.methodName(parameters,function(response){
   /* your success actions*/
   $scope.variable=response;
   });
});

In the second case your error is handled in the factory itself. How ever you can also use errorcallback function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM