paj28
paj28

Reputation: 2320

Can a call to $http be made more concise?

I find myself frequently using this construct in my controllers:

$http({method: 'GET', url: '../ajax/mycallback', cache: false}).
success(function(data) {
    $scope.data = data;
});

Is there any way to make this more concise? In particular, is there a kind of "default success method" that just stores the result on the scope? Also, is there a way to globally set cache to false, so I can use $http.get() ?

Upvotes: 1

Views: 75

Answers (3)

JeffryHouser
JeffryHouser

Reputation: 39408

I don't have issue with the other answers, but just in case they are over-thinking it. You can do this:

var genericSuccessFunction = function(data) {
    $scope.data = data;
}

You can create your result function as part of the controller and save it as a controller local variable.

Then you just need to pass the result function into the success:

$http({method: 'GET', url: '../ajax/mycallback', cache: false}).success(genericSuccessFunction);

In my experience, I often find myself using this approach for an error function, but I don't often find myself able to use generic success functions.

Upvotes: 0

Mr_Mig
Mr_Mig

Reputation: 783

Option 1: you only need to pass the value to $scope

$http returns a promise, so you can share the returning result directly with the scope:

$scope.data = $http({method: 'GET', url: '../ajax/mycallback', cache: false})

Angular has automatic promise fulfillment support in templates. So if you assign the data to templates, it will automatically trigger the digest cycle upon fulfillment (read: it will trigger the update when the $http will succeed).

But in this case I would suggest you to use $resource instead of $http and incapsulate the $resource creation as a service.

You also can use $resource the same way, as it has natural automatic promise fulfillment. Natural states that promises will be replaced with actual values (this logic includes arrays support!):

$scope.data = MyResourceService(...)

Option 2: you have a more complex callback

You can simply create a factory function to create a closure within a specific scope:

function cb(scope, scopeObjName) {
    return function(data){
        scope["scopeObjName"] = data;
        // common logic goes here
    } 
}

and use it like this:

$http({method: 'GET', url: '../ajax/mycallback', cache: false})
.success(cb($scope, "data"))

As you can see, the answer depends on the actual usecase and can be improved further.

Upvotes: 1

calebboyd
calebboyd

Reputation: 5753

You could do the following:

myApp.config(function($httpProvider){
    $httpProvider.defaults.cache = false;  
});

as for your callback, If that is all you're doing, the anonymous function is the best option. Otherwise you'd have to bind a generic function every http invocation and pass it a context..like this:

$http.get(...).success(standardSuccess.bind({$scope:$scope,p:'data'}));

function standardSuccess(data){
    this.$scope[this.p] = data;  
}

Then you would just keep that in an injectable somewhere. But as you can see is more verbose and less readable. And slower.

Another option is to pass the scope into the httpConfig itself. and use an interceptor to set your property. (as the config is received in an interceptor. Roughly like:

myApp.config(function($httpProvider){
    $httpProvider.defaults.cache = false;
    $httpProvider.interceptors.push('defaultHttpSetter');
});
myApp.factory('defaultHttpSetter',function($q){
   return {
       'response': function(response){
             response.config.scope[response.config.prop] = response.data;
             return $q.when(response);
        }
   };    
});

Which would be used like..

$http.get('/myurl',{scope:$scope,prop:'data'});

Upvotes: 1

Related Questions