Angular promise after calling a service with $http - javascript

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.

Related

Problem inizialise a global variable AngularJS by calling a REST service

I want to create a global variable (httpTimeout) initialize at the start, contains a Long value returned by a synchrone call Rest Service and used it in different service
(
function () {
'use strict';
angular
.module('module')
.factory('MyService', function (
$http,
$q
){
var service = {};
var httpTimeout = function() {
return $http({
method: 'GET', '.../rest/getHttpTimeOut'
}).then(function (response) {
return response.data;
}).catch(function (err) {
return 30000;
});
};
service.myService1= function (Model) {
return $http({
method: 'POST', '..../rest/callRestService1',
data: Model, timeout : httpTimeout
}).then(function (response) {
return response.data;
});
};
service.myService2= function (Model) {
return $http({
method: 'POST', '..../rest/callRestService2',
data: Model, timeout : httpTimeout
}).then(function (response) {
return response.data;
});
};});
My rest service
#RequestMapping(value = "/getHttpTimeOut", method = RequestMethod.GET)
#ResponseBody
public long getHttpTimeOutValue() {
return timeoutValue;
}
how i can retrieve this value globally (httpTimeout) for use in other services
Thank you for your help
if your question is how to do something on application start :
look at that
After your application start you can use another service to store the value.
Also if you want to apply this comportement for all request take a look to interceptor

Angular - How can i pass a parameter into a deferred promise?

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
});

Angular Promise Response Checking

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>

How to make the controller wait for factory response in angularjs?

I am trying to get the response from factory to controller. but when i am calling a function of factory from controller, then the controller not waiting for its response. and giving "undefined".
here it is my controller.js
app.controller('customerCommentsController',function($scope,$http,$stateParams,$sce,$timeout,Comments){
var commentsdata = '';
Comments.init(1,5);
$scope.total_comments = Comments.total();
console.log($scope.total_comments); //undefined
$scope.positive_comments = Comments.positive();
console.log($scope.positive_comments); //undefined
$scope.commentsdata = Comments.getcomments(1,30);
console.log($scope.commentsdata); //undefined
});
here I am calling init() method which gets the response from ajax, which takes some time to execute , but before it could complete, the other 2 statement (total() and positive() method) execute below the init method. and that not gets initialize because of init method not completed. and that why I am getting undefined.
and same problem is coming when I am calling getcomments method which doesn't wait for its response.
here it is my factory
app.factory("Comments",function($http,$timeout,$q){
var commentshtml = [];
var commentshtml1 = [];
return {
init : function(start,end) {
var request = $http({
method:"post",
url:"/comments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
request.success(function(data){
commentshtml = data;
});
},
total : function() {
return commentshtml.total_comment;
},
positive : function(){
return commentshtml.per_positive_comment;
},
getcomments : function(start,end) {
var promise = $http({
method:"post",
url:"/comments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
promise.success(function(data){
commentshtml1 = data.comments;
console.log(commentshtml1); //giving the object
return commentshtml1;
});
}
};
it's better to use $q module to work with asynchronous functions in angular. Read this docs:
$q documentation
Do this way:
In factory
return {
init : function(start,end) {
return $http({ //return the promise
method:"post",
url:"/comments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
}
getcomments : function(start,end) {
return $http({ //return the promise
method:"post",
url:"/comments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
}
In Controller
Comments.init(1,5).then(function(){
$scope.total_comments = Comments.total();
console.log($scope.total_comments);
$scope.positive_comments = Comments.positive();
console.log($scope.positive_comments);
});
Comments.getcomments(1,30).then(function(data){
$scope.commentsdata =data.comments;
})
Or the best way use resolve property in ng-route or ui-router
You are performing asynchronous request, the problem is that you retrieve data before she is defined.
A good practice is to use promise. You hace to know that the $http service return promises, and has some callback method, like .success() and .then() for example.
For promise, angular provide us a pretty good tool : $q.defer().
$q.defer() is a promise manager from the deferred API.
$q.defer() get 2 methods :
resolve(value) : which resolve our associated promise, by giving her the final value
reject(reason) : which resolve an promise error.
So you can do the following :
Controller
(function(){
function Controller($scope, Comments) {
//Retrieve our init promise
var promise_init = Comments.init();
//Retrieve our total promise
var promise_total = Comments.total();
promise_init.then(function(){
//Return promise for chaining
return promise_total;
}).then(function(total){
//Retrieve total of comments
$scope.total = total;
}).catch(function(err){
//Catch error of total comments
$scope.total = err;
});
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
Service
(function(){
function Service($q){
var commentshtml = [];
function init(){
//Create defer object
var defer = $q.defer();
commentshtml = ['a', 'b', 'c'];
//Simulate latency
setTimeout(function(){
//Resolve our promise
defer.resolve();
}, 2000);
//Return a promise
return defer.promise;
}
function total(){
var defer = $q.defer();
commentshtml.length < 3
? defer.reject('error length')
: defer.resolve(commentshtml.length);
return defer.promise;
}
return {
init: init,
total: total
};
}
angular
.module('app')
.factory('Comments', Service);
})();
HTML
<body ng-app='app' ng-controller='ctrl'>
<h2>Total : {{total}}</h2>
</body>
You can see the Working Plunker
Write your all $scope variable in then function.
So your Controller.js :
app.controller('customerCommentsController',function($scope,$http,$stateParams,$sce,$timeout,Comments){
var commentsdata = '';
Comments.init(1,5).then(function(){
$scope.total_comments = Comments.total();
console.log($scope.total_comments); //undefined
$scope.positive_comments = Comments.positive();
console.log($scope.positive_comments); //undefined
$scope.commentsdata = Comments.getcomments(1,30);
console.log($scope.commentsdata); //undefined
}
});
You have to return your $http request.
So your init function look like :
init : function(start,end) {
return $http({
method:"post",
url:"/comments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
}).success(function(data){
return commentshtml = data;
});
}
And your Factory :
app.factory("Comments",function($http,$timeout,$q){
var commentshtml = [];
var commentshtml1 = [];
return {
init : function(start,end) {
return $http({
method:"post",
url:"/comments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
}).success(function(data){
return commentshtml = data;
});
},
total : function() {
return commentshtml.total_comment;
},
positive : function(){
return commentshtml.per_positive_comment;
},
getcomments : function(start,end) {
var promise = $http({
method:"post",
url:"/comments.php",
data: {start:start,end:end},
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
});
promise.success(function(data){
commentshtml1 = data.comments;
console.log(commentshtml1); //giving the object
return commentshtml1;
});

How to use HTTP.GET in AngularJS correctly? In specific, for an external API call?

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);
}
);
})

Categories

Resources