Service.js
myService.serviceName = function (userId) {
return $http({
method: 'POST',
url: '/someUrl'
}).then(function successCallback(response) {
return response.data;
}, function errorCallback(response) {
console.log('Service errorCallback');
console.log(response);
});
};
Controller.js
myService.ControllerName(data.id)
.then(function successCallback(data) {
//do processing here
}, function errorCallback(response) {
toaster.pop({
type: 'error',
title: 'Display Error Message!'
});
});
In service, we are getting error status code in console viz -1, -2 and based on that code we are displaying custom error message to the user.
How do I pass error (message/code) from service to controller ?
The first thing that comes to my mind is to accept callbacks from the Controller.
myService.serviceName = function (userId) {
return $http({
method: 'POST',
url: '/someUrl'
})
};
And in your Controller:
myService.serviceName(123).then(function(response) {
// Do the processing.
}, function(error) {
// Check the error and change the UI accordingly.
});
If you need to make the processing within the service, you might want to use the $q service. In this case, you would need to inject it into your Service.
myService.serviceName = function (userId) {
var defer = $q.defer();
$http({
method: 'POST',
url: '/someUrl'
}).then(function (response) {
// Do the processing.
defer.resolve(response);
}).catch(function (error) {
defer.reject(error);
});
return defer.promise;
};
In your controller:
myService.serviceName(123).then(function(response) {
// Indicate that everything went OK.
}, function(error) {
// Check the error and change the UI accordingly.
});
You could add functionality to add callbacks to the service.
This way the controller can register its own callback method to the service. Which in its turn will call said callback method when the error occurs. Notifying the controller of the occurred error and desired message.
Working on my first Angular app here so excuse me if question not clear.
I have a service which gets from my api using a group variable in the header.
var theReq = {
method: 'GET',
url: API + '/homeq',
headers: {
'group': 'mobile'
}
};
$http(theReq)
.then(function(data){
deferred.resolve(data);
})
self.getResults = function() {
return deferred.promise;
}
The issue I'm facing is with using the group variable that i specify rather than that preset one.
I can surely pass it into that function (i.e. self.getResults = function(groupToGet)) but how would it get from there to theReq that I process?
Any help appreciated.
Thanks.
You need to modify your function in following manner. $q is the service to create deferred objects. You need to inject it.
self.getResults = function(groupToSet) {
var deferred = $q.defer();
var theReq = {
method: 'GET',
url: API + '/homeq',
headers: {
'group': groupToSet
}
};
$http(theReq)
.then(function(data){
deferred.resolve(data);
})
return deferred.promise;
}
and you can use promise as
self.getResults("mobile").then(function(data) {
//success function here.
}).catch(function(error) {
//error function here
});
I am doing some http calls in Angular and trying to call a different service function if an error occurs. However, regardless of my original service call function return, the promise it returns is always "undefined". Here is some code to give context:
srvc.sendApplicantsToSR = function (applicant) {
var applicantURL = {snip};
var promise = $http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'POST',
url: applicantURL,
data: applicant
})
.success(function (data) {
return data;
})
.error(function (error) {
return [];
});
return promise;
};
Then, in the controller:
for (var applicant in $scope.applicants) {
$scope.sendATSError($scope.sendApplicantsToSR($scope.applicants[applicant]), applicant);
}
$scope.sendATSError = function (errorCheck, applicantNumber) {
if (angular.isUndefined(errorCheck)) {
console.log(errorCheck);
AtsintegrationsService.applicantErrorHandling($scope.applicants[applicantNumber].dataset.atsApplicantID);
}
};
However, it is always sending errors because every response is undefined. How can I differentiate between the two returns properly? Thank you!
Looking at angular documentation, the sample code is
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
based on that - your first code snippet should be
srvc.sendApplicantsToSR = function(applicant) {
var applicantURL = {
snip
};
return $http({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'POST',
url: applicantURL,
data: applicant
});
};
As others have said, $http's .success() and .error() are deprecated in favour of .then().
But you don't actually need to chain .then() in .sendApplicantsToSR() as you don't need (ever) to process the successfully delivered data or to handle (at that point) the unsuccessful error.
$scope.sendApplicantsToSR = function (applicant) {
var applicantURL = {snip};
return $http({
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
url: applicantURL,
data: applicant
});
};
Now, in the caller (your line of code in the for loop), a promise is returned (not data) and that promise will, on settling, go down its success path or its error path. Exactly what happens on these paths is determined entirely by the callback functions you write in one or more chained .thens .
So what you need to write is a kind of inside-out version of what's in the question - with $scope.sendApplicantsToSR() on the outside and $scope.sendATSError() on the inside - and linked together with a .then().
for (var prop in $scope.applicants) {
var applicant = $scope.applicants[prop];
$scope.sendApplicantsToSR(applicant).then(null, $scope.sendATSError.bind(null, applicant));
}
// Above, `null` means do nothing on success, and
// `function(e) {...}` causes the error to be handled appropriately.
// This is the branching you seek!!
And by passing applicant, the error handler, $scope.sendATSError() will simplify to :
$scope.sendATSError = function (applicant) {
return AtsintegrationsService.applicantErrorHandling(applicant.dataset.atsApplicantID); // `return` is potentially important.
};
The only other thing you might want to know is when all the promises have settled but that's best addressed in another question.
You should return your promisse to be handled by the controller itself.
Simplifying:
.factory('myFactory', function() {
return $http.post(...);
})
.controller('ctrl', function(){
myFactory()
.success(function(data){
// this is your data
})
})
Working example:
angular.module('myApp',[])
.factory('myName', function($q, $timeout) {
return function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve('Foo');
}, 2000);
return deferred.promise;
}
})
.controller('ctrl', function($scope, myName) {
$scope.greeting = 'Waiting info.';
myName().then(function(data) {
$scope.greeting = 'Hello '+data+'!';
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="ctrl">
{{greeting}}!
</div>
I m actually developping an application with angularjs, and I m facing a problem with $http, and the result of an asynchronous service request to my webservice.
Actually, I m using this code :
var promise = undefined;
UserService.getAll = function (callback) {
promise = $http({
url: __ADRS_SRV__ + "users",
method: "GET",
isArray: true
}).success(function(data){
return data;
}).error(function(data){
return $q.reject(data);
});
return promise;
}
This doesnt work, and give me some stuff like, I dont know why :
To know : in my controller, I want to use a really simple syntax like
var data = UserService.getAll();
Do you have any idea how should I process to access my data correctly ?
Thanks for advance
you get the promise in return. There are multiple ways to use this promise.
Example 1 (Use promise in service and return reference of an object):
UserService.getAll = function () {
var dataWrapper = {
myData: {},
error: null
};
$http({
url: __ADRS_SRV__ + "users",
method: "GET",
isArray: true
}).success(function(data){
dataWrapper.myData = data;
}).error(function(data){
dataWrapper.error = true;
return $q.reject(data);
});
return dataWrapper;
}
Example 2 (Return promise and use it directly in the controller):
// service
UserService.getAll = function () {
return $http({
url: __ADRS_SRV__ + "users",
method: "GET",
isArray: true
});
}
// controller
var promise = UserService.getAll();
promise.success(function(data) {
$scope.data = data;
});
Example 3 (Use regular callback):
// service
UserService.getAll = function (cb) {
$http({
url: __ADRS_SRV__ + "users",
method: "GET",
isArray: true
}).success(cb);
}
// controller
UserService.getAll(function(data) {
$scope.data = data;
});
The "stuff" you mention is the very promise you create and return.
I have the following code in the controller.js,
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = dataService.getData();
});
But, I think I m probably making a mistake with CORS related issue. Can you please point me to the correct way to make this call? Thanks much!
First, your success() handler just returns the data, but that's not returned to the caller of getData() since it's already in a callback. $http is an asynchronous call that returns a $promise, so you have to register a callback for when the data is available.
I'd recommend looking up Promises and the $q library in AngularJS since they're the best way to pass around asynchronous calls between services.
For simplicity, here's your same code re-written with a function callback provided by the calling controller:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function(callbackFunc) {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, call our callback
callbackFunc(data);
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData(function(dataResponse) {
$scope.data = dataResponse;
});
});
Now, $http actually already returns a $promise, so this can be re-written:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
// $http() returns a $promise that we can add handlers with .then()
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(dataResponse) {
$scope.data = dataResponse;
});
});
Finally, there's better ways to configure the $http service to handle the headers for you using config() to setup the $httpProvider. Checkout the $http documentation for examples.
I suggest you use Promise
myApp.service('dataService', function($http,$q) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
deferred = $q.defer();
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, we can resolve promise and we can access it in controller
deferred.resolve();
}).error(function(){
alert("error");
//let the function caller know the error
deferred.reject(error);
});
return deferred.promise;
}
});
so In your controller you can use the method
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
promises are powerful feature of angularjs and it is convenient special if you want to avoid nesting callbacks.
No need to promise with $http, i use it just with two returns :
myApp.service('dataService', function($http) {
this.getData = function() {
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data;
}).error(function(){
alert("error");
return null ;
});
}
});
In controller
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
Try this
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
Just setting useXDomain = true is not enough. AJAX request are also send with the X-Requested-With header, which indicate them as being AJAX. Removing the header is necessary, so the server is not rejecting the incoming request.
So you need to use what we call promise. Read how angular handles it here, https://docs.angularjs.org/api/ng/service/$q. Turns our $http support promises inherently so in your case we'll do something like this,
(function() {
"use strict";
var serviceCallJson = function($http) {
this.getCustomers = function() {
// http method anyways returns promise so you can catch it in calling function
return $http({
method : 'get',
url : '../viewersData/userPwdPair.json'
});
}
}
var validateIn = function (serviceCallJson, $q) {
this.called = function(username, password) {
var deferred = $q.defer();
serviceCallJson.getCustomers().then(
function( returnedData ) {
console.log(returnedData); // you should get output here this is a success handler
var i = 0;
angular.forEach(returnedData, function(value, key){
while (i < 10) {
if(value[i].username == username) {
if(value[i].password == password) {
alert("Logged In");
}
}
i = i + 1;
}
});
},
function() {
// this is error handler
}
);
return deferred.promise;
}
}
angular.module('assignment1App')
.service ('serviceCallJson', serviceCallJson)
angular.module('assignment1App')
.service ('validateIn', ['serviceCallJson', validateIn])
}())
Using Google Finance as an example to retrieve the ticker's last close price and the updated date & time. You may visit YouTiming.com for the run-time execution.
The service:
MyApp.service('getData',
[
'$http',
function($http) {
this.getQuote = function(ticker) {
var _url = 'https://www.google.com/finance/info?q=' + ticker;
return $http.get(_url); //Simply return the promise to the caller
};
}
]
);
The controller:
MyApp.controller('StockREST',
[
'$scope',
'getData', //<-- the service above
function($scope, getData) {
var getQuote = function(symbol) {
getData.getQuote(symbol)
.success(function(response, status, headers, config) {
var _data = response.substring(4, response.length);
var _json = JSON.parse(_data);
$scope.stockQuoteData = _json[0];
// ticker: $scope.stockQuoteData.t
// last price: $scope.stockQuoteData.l
// last updated time: $scope.stockQuoteData.ltt, such as "7:59PM EDT"
// last updated date & time: $scope.stockQuoteData.lt, such as "Sep 29, 7:59PM EDT"
})
.error(function(response, status, headers, config) {
console.log('### Error: in retrieving Google Finance stock quote, ticker = ' + symbol);
});
};
getQuote($scope.ticker.tick.name); //Initialize
$scope.getQuote = getQuote; //as defined above
}
]
);
The HTML:
<span>{{stockQuoteData.l}}, {{stockQuoteData.lt}}</span>
At the top of YouTiming.com home page, I have placed the notes for how to disable the CORS policy on Chrome and Safari.
When calling a promise defined in a service or in a factory make sure to use service as I could not get response from a promise defined in a factory. This is how I call a promise defined in a service.
myApp.service('serverOperations', function($http) {
this.get_data = function(user) {
return $http.post('http://localhost/serverOperations.php?action=get_data', user);
};
})
myApp.controller('loginCtrl', function($http, $q, serverOperations, user) {
serverOperations.get_data(user)
.then( function(response) {
console.log(response.data);
}
);
})