angular 1.6.1 http request from service - angularjs

angular 1.6.1 has removed .success and .error in service $http for use .then and .catch.
Now my answer is:
It makes sense that I have written in my code? because now I'm confused on how the controller talks to the service
I have a controller for login (example):
LoginCTRL
User.login(data).then(
function(response){
//do something
},function(err){
//do somethig
});
And I have User service:
myapp.service('User', function User($q, $http) {
return {
login: function(credentials){
return $http.post('login',{data:data}).then(function onSuccess(response) {
return response;
}).catch(function onError(response){
return response;
});
},
}
It's correct write service.method().then in controller, now that there is no more $q.defer().resolve(data) or $q.defer().reject(reason)

try:
myapp.service('User', function User($q, $http) {
return {
login: function(credentials) {
var deferred = $q.defer();
$http.post('login', {
data: data
}).then(onSuccess, onFailure);
function onSuccess(response) {
deferred.resolve(response);
}
function onFailure(response) {
deferred.reject(response);
}
return deferred.promise;
}
}
}

Related

Http Function in factory not work in controller when use the "then"

I am trying to call the http function of Factory in controller ,it does not work when I use the .then
My code is as follows:
module :
var brandlistmodule = angular.module('newApp')
factory :
brandlistmodule.factory('BrandListFactory',["$http","$routeParams",function($http,$routeParams){
console.log(2)
return {
a: function(response){
console.log('1');
return $http.get("/restful_api/category_1/?format=json").then(function(response){
console.log('3');
return response.data;
});
},
b: function(response){
return $http.get("/restful_api/category_refer_a/?format=json").then(function(response){
return response.data;
});
},
c: function(response){
return $http.get("/restful_api/brand_test_search/?format=json").then(function(response){
result = response.data
return result;
});
},
}
}])
controller:
brandlistmodule.controller('brandlistCtrl', ['BrandListFactory','$scope','$rootScope','$http',function (BrandListFactory,$scope,$rootScope,$http) {
$scope.$on('$viewContentLoaded', function () {
$rootScope.category = function(){
BrandListFactory.a.success(function(data){
console.log('9');
$rootScope.category =data
});
};
In the console it only can show the "2",if I change the controller as follows ,it will work properly
brandlistmodule.controller('brandlistCtrl', ['BrandListFactory','$scope',function (BrandListFactory,$scope) {
$scope.$on('$viewContentLoaded', function () {
BrandListFactory.BrandCategoryList()
your problem is you're calling Then() inside the factory...so what you can do is :
1 - NO CALLING THEN .. but RETURN ALL YOUR $http request to the caller of the Factory .. like:
brandlistmodule.factory('BrandListFactory',["$http","$routeParams",function($http,$routeParams){
console.log(2)
return {
a: function(response){
console.log('1');
return $http.get("/restful_api/category_1/?format=json");
},
b: function(response){
return $http.get("/restful_api/category_refer_a/?format=json");
},
c: function(response){
return $http.get("/restful_api/brand_test_search/?format=json");
},
}
}])
2- use $q and make by yourself the asyncron chain .. like:
brandlistmodule.factory('BrandListFactory',["$http","$routeParams","$q",function($http,$routeParams,$q){
console.log(2)
return {
a: function(response){
var deferred = $q.defer();
console.log('1');
return $http.get("/restful_api/category_1/?format=json").then(function(response){
console.log('3');
deferred.resolve( response.data);
}).catch(function(err){
deferred.reject(err);
});
return deffered.promise;
}
// and same for others
}
}])
I would suggest to creat a Service which is responsible for all of your http calls something like this
.service('HttpService', ['$rootScope', '$http', 'Ls', 'CommonService', 'DateService', function ($rootScope, $http, Ls, CommonService, DateService) {
return {
CallService: function (url, callback) {
$http.get(url)
.success(function (data, status) {
callback(data, status);
}).error(function (data, status) {
callback(data, status);
});
}
}
});
If you pass the parameter callback into the HttpService.CallService then you can call the callback in the success or error function of the http.get call.
For example in the Controller you can do
HttpService.CallService('/restful_api/category_refer_a/?format=json', function (data) {
console.log(data)
//do something with your data
});
So in your example you could do:
$scope.$on('$viewContentLoaded', function () {
HttpService.CallService('/restful_api/category_refer_a/?format=json', function (data) {
console.log('9');
$rootScope.category =data
});
});
or you simply change your calls to
b: function(callback){
return $http.get("/restful_api/category_refer_a/?format=json").then(function(response){
callback(response.data);
});
},
and
BrandListFactory.b(function(data){
console.log('9');
$rootScope.category =data
});
Hope this helps you

How to make a $http request from the rest client in AngularJs?

Have this scenario when I make a request via $http in the first service, and then I want to manipulate the data in other service. For some reassons my returned object is empty. Any advice ?
.factory('widgetRestService',['$http','$log',function($http,$log){
var serviceInstance = {};
serviceInstance.getInfo = function(){
var request = $http({method: 'GET', url: '/rest/widgets/getListInfoDashboards'})
.then(function(success){
serviceInstance.widgets = success.data;
$log.debug('serviceInstance.widgets SUCCESS',serviceInstance.widgets);
},function(error){
$log.debug('Error ', error);
$log.debug('serviceInstance.widgets ERROR',serviceInstance.widgets);
});
return request;
};
serviceInstance.getAllWidgets = function () {
if (serviceInstance.widgets) {
return serviceInstance.widgets;
} else {
return [];
}
};
return serviceInstance;
}])
.factory('OtherService',['widgetRestService','$log', function(widgetRestService, $log){
widgetRestService.getInfo();
// and now I want to return widgetRestService.widgets [{things},{things},{things}]
return widgetRestService.getAllWidgets(); // returns []
}])
Result: [ ]
You must wait for your HTTP request to complete before trying to access the data that it returns. You can do this by accessing getAllWidgets within a then attached to the Promise returned by getInfo.
.factory('OtherService', ['widgetRestService','$log', function(widgetRestService, $log) {
return widgetRestService.getInfo().then(function () {
return widgetRestService.getAllWidgets();
});
}])
Consume OtherService somewhere:
OtherService.then(function (widgets) {
// do something with `widgets`...
});
It seems you have to return promise instead of response to get the data from another service.
serviceInstance.getInfo = function(){
var deferred = $q.defer();
$http({method: 'GET', url: '/rest/widgets/getListInfoDashboards'})
.then(function(success){
deferred.resolve(success.data);
},function(error){
$log.debug('Error ', error);
$log.debug('serviceInstance.widgets ERROR',serviceInstance.widgets);
});
return deferred.promise;
};
widgetRestService.getInfo() is returning a promise, so you have to wait for its resolution:
.factory("OtherService", ["widgetRestService", "$log", "$q"
function (widgetRestService, $log, $q) {
var deferred = $q.defer();
widgetRestService.getInfo().then(function () {
// only here, you're sure `serviceInstance.widgets` has been set (unless an error occurred when requesting the api)
deferred.resolve(widgetRestService.getAllWidgets());
});
return deferred.promise;
}])
Then, e.g. in a controller:
.controller("SomeController", ["$scope", "OtherService"
function ($scope, OtherService) {
OtherService.then(function (allWidgets) {
$scope.allWidgets = allWidgets;
});
}])

Why do i have to use return twice and how does it work?

I wrote a wrapper for the $http service in angular using a service. Why do i have to return bothe the http call and my result to have it available in a controller?
this is the function in the service:
this.fetchData = function(url, parameters)
{
if (parameters)
{
return $http.get(url, {params: parameters}).then(
function (response) {
console.log(response);
return response.data.data;
},
function (response) {
console.log(response);
});
}
else
{
return $http.get(url).then(
function (response) {
console.log(response);
},
function (response) {
console.log(response);
}
);
}
}
and this is where i call it in the controller:
test.fetchData('/jewelry-room/move-user.action', {user:2000, task:7}).then(
function (response) {
console.log(response);
},
function (response) {
console.log(response);
}
);
Because what you return from the factory is a promise: return $http.get().then(). Since your factory has the callback function inside then, so the promise is resolved. In this case, the function inside controller then block will not be called.
You need to return again in order to have access to the response data inside the controller.
Alternatively, just return $http.get() from the factory.
You could just return the promise to your controller by using $q:
var fetchData = function (url, params) {
if (params) {
var deferred = $q.defer();
$http.get(url, {params: params}).success(deferred.resolve).error(deferred.reject)
return deferred.promise;
} else {
var deferred = $q.defer();
$http.get(url).success(deferred.resolve).error(deferred.reject)
return deferred.promise;
}
}
Then inside your controller you can handle the promise.

Setting up a service with $q

I am trying to set up a service with $q (and resangular), so in a controller I could then call
myservice.get.then(function(data){
//use data
}
Right now I have
.service(urlService,
function($q, Restangular) {
this.get = function(newURl) {
return $q(function(resolve, reject) {
Restangular.one(newURl).get()
.then(resolve)
.catch(reject);
});
};
}
If I inject into a controller and call
urlService.get(newUrlObject).then(function(data){
console.log(data);
});
this does not seem to work. I could use some help getting this right, thanks!
You have to call resolve and reject:
return $q(function(resolve, reject) {
Restangular.one(newURl).get()
.then(function(data) {
resolve(data)
})
.catch(function(whatever) {
reject(whatever);
});
But Restangular.one(newURl).get() already returns a promise, so wrapping the code into another deferred doesn't make much sense. Id rather use the promise directly:
this.get = function(newURl) {
return Restangular.one(newURl).get();
};
May be you should use $q.refer, like this:
.service(urlService,
function($q, Restangular) {
this.get = function(newURl) {
var deferred = $q.defer();
Restangular.one(newURl).get()
.then(function() {
deferred.resolve();
})
.catch(function(){
deferred.reject();
});
return deferred.promise();
};
}
Reference: https://docs.angularjs.org/api/ng/service/$q

Is there a way I can return a promise from a $resource without needing to use $q?

I have coded the following service:
angular.module('App')
.factory('TestService', ['$http', '$q', '$resource', function (
$http, $q, $resource) {
var TestResource = $resource('/api/Tests', {}, {
saveData: { method: 'PUT' },
deleteData: { method: "DELETE", params: { TestId: 0 } }
});
var factory = {
query: function (selectedSubject) {
var deferred = $q.defer();
TestResource.query({ subjectId: selectedSubject },
function (resp) {
deferred.resolve(resp);
}
);
return deferred.promise;
//return Test.query({ subjectId: selectedSubject });
}
}
return factory;
}]);
In my controller I am calling it this way:
TestService.query($scope.selectedSubject)
.then(function (result) {
$scope.gridData = result;
}, function (result) {
alert("Error: No data returned");
});
Is there a way that I could cut out a few lines of code by not having $q in my service. Is there a way that I could return a promise from the $resource? I have tried the commented out code but that gives me an error saying there is no ".then" method.
$resource can't return a promise in the current stable version of Angular (1.0.8), but it looks like it'll come in version 1.2. It was added in v1.1.3 (v 1.1 is the unstable branch):
$resource: expose promise based api via $then and $resolved (dba6bc73)

Resources