I want to get data pass from a function, the data successfully return inside the success response. However I can't return the data from the function itself.
function getStatusPublished(dating, product)
{
var datas = "";
var success = function(response, status, headers, config){
datas = response;
}
var error = function(error, status, headers, config){
datas = "error";
}
var cdnss = "htttp://application_ajax";
$http.post(cdnss+"&pblishDateVacan="+dating+"&ProjectID="+product)
.success(success).error(error);
console.log(datas);
}
In the console.log, it just said undefined.
Please help. Thanks.
The $http.post method returns a promise; not data.
To return a promise, simply use a return statement.
function getStatusPublished(dating, product) {
var url = "htttp://application_ajax";
var postData = {};
var params = {
pblishDataVacan: dating,
ProjectId: product
};
var config = { params: params };
var promise = $http.post(url,postData,config);
//return promise
return promise;
}
To get the data from the promise, use the .then method:
var promise = getStatusPublished(d, p);
promise.then( function(response) {
$scope.data = response.data;
return response.data;
}).catch ( function(response) {
console.log(response.status);
throw response;
});
Related
I have written a custom angular service that returns the session id after making a post-call to the WCF service. I can see on the chrome's network tab that the call has returned the session-id but when I try to return it through $http.post to the caller it returns "{}" object.
I've followed all the questions/answers related to this problem in stackoverflow, etc. but to no avail. I know there is a problem with the handling of promise that was returned by the post-call but I don't know and not able to pin-point what's wrong and where.
This is the custom service.
angApp.service('RPCService', function($http) {
var url_login = 'http://xxxxxxx';
this.Login = function(request) {
return $http.post(url_login, request)
.then(function (result) {
return result.data;
},
function (data, status) {
console.log(data + status);
});
};
This is the caller.
angApp.controller('exportController', ['$scope', 'RPCService', function ($scope, RPCService) {
$scope.export = {};
$scope.exportLogin = function(){
var req = {
"SiteId" : $scope.export.xxx,
"UserName" : $scope.export.xxx,
"Password" : $scope.export.xxx
};
$scope.export.sessionId = RPCService.Login(req);
};
I expected the output as "SessionId" : "xxxxxxxx" but I am getting "{}"
$http.post returns a promise and that is what your service method is returning
Change
$scope.export.sessionId = RPCService.Login(req);
To
RPCService.Login(req).then(function(data){
$scope.export.sessionId = data;
})
The signature of the error handler is wrong:
ERRONEOUS
return $http.post(url_login, request)
.then(function (result) {
return result.data;
},
function (data, status) {
console.log(data + status);
});
BETTER
return $http.post(url_login, request)
.then(function (result) {
return result.data;
},
function (response) {
var data = response.data;
var status = response.status;
console.log(data + status);
//IMPORTANT re-throw error
throw response;
});
It is important to re-throw an error in a rejection handler. Otherwise the rejected promise will be converted to a fulfilled promise with a value of undefined.
Adding the single parameter for error callback and then using the promise accessor with .then keyword on the caller fixed the issue. Following is the code.
this.Login = function(request) {
return $http.post(url_login, request)
.then(function (result) {
return result.data;
},
function (response) {
var data = response.data;
var status = response.status;
console.log(data + " | " + status);
throw response;
});
};
On controller
RPCService.Login(req).then(function(data){
$scope.export.sessionId = data.SessionId;
});
I'm trying to make couple of HTTP requests, one inside another, and I'm having a trouble restructuring my JSON object.
I have a factory function, first of all i'm trying to get all the teams, each team has an Id, and then i'm getting all the news for each team with the id related, and putting that news in the first JSON object.
but this is not working !
.factory('teamsFactory', function ($http,CacheFactory,LocaleManager,$q)
{
teams.Getteams= function()
{
var zis=this;
var promise=$http({method:"GET",url:"http://www.myserver/teams"});
promise.then(function(response){
for (var i=0;i<response.data.length;i++) {
zis.getTeamsNews(response.data[i].idTeam).then(function(newsresponse){
response.data[i].news=newsresponse.data;
});
}
},alert('error'));
return promise;
}
teams.getTeamsNews= function(idTeam)
{
var promise=$http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam});
promise.then(null,alert('error'));
return promise;
}
});
I think it's better to push all the $http promises into an array and then use $q.all() to group them together rather than calling them each individually in a loop. Try this:
Note I had to move some of your functions around and create dummy data etc. so you will have to alter it slightly to fit your app.
DEMO
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, teamsFactory) {
$scope.name = 'World';
teamsFactory.Getteams()
.then(function(data){
$scope.teamsData = data;
});
});
app.factory('teamsFactory', function ($http, $q){
var teams = {};
teams.getFavoriteTeamsNews = function(teamId){
return $http
.get('news.json')
.then(function(response){
console.log('gtTeamNews response', response);
return response.data[teamId];
})
}
teams.Getteams = function(){
var zis = this,
httpConfig = {
method : "GET",
url : "teams.json"
};
return $http(httpConfig)
.then(function(response){
var teamId, promise,
requests = [];
for(var i = 0; i <response.data.length; i++){
teamId = response.data[i].idTeam;
promise = teams.getFavoriteTeamsNews(teamId);
requests.push(promise);
}
return $q
.all(requests)
.then(function(responses){
angular.forEach(responses, function(newsresponse, index){
response.data[index].news = newsresponse;
});
return response.data;
});
})
.catch(function(error){
console.log('error', error);
});
}
return teams;
// teams.TeamsNews= function(idTeam){
// return $http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam})
// .catch(function(){
// alert('error')
// });
// }
});
update
You could also re-factor the above to take advantage of promise chaining which makes it much cleaner in my opinion. This should give the same output but is more 'flat', i.e. has less indentation/callback hell:
DEMO2
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, teamsFactory) {
$scope.name = 'World';
teamsFactory.Getteams()
.then(function(data){
$scope.teamsData = data;
});
});
app.factory('teamsFactory', function ($http, $q){
var responseData,
teams = {};
teams.getFavoriteTeamsNews = function(teamId){
return $http
.get('news.json')
.then(function(response){
console.log('gtTeamNews response', response);
return response.data[teamId];
})
}
teams.Getteams = function(){
var zis = this,
httpConfig = {
method : "GET",
url : "teams.json"
};
return $http(httpConfig)
.then(function(response){
var teamId, promise,
requests = [];
responseData = response.data;
for(var i = 0; i < responseData.length; i++){
teamId = responseData[i].idTeam;
promise = teams.getFavoriteTeamsNews(teamId);
requests.push(promise);
}
return $q.all(requests);
})
.then(function(responses){
angular.forEach(responses, function(newsresponse, index){
responseData[index].news = newsresponse;
});
return responseData;
})
.catch(function(error){
console.log('error', error);
});
}
return teams;
});
eventually something like that .. this is raw solution .. could be enhanced with caching ...
var module = angular.module('myapp', []);
module.factory('teamsFactory', function ($http,CacheFactory,LocaleManager,$q)
{
function ExtractTeamFromData(data){
// TODO
console.log("TODO: Exctract teams from data ...");
}
function FindTeamById(teams, tgeamId){
// TODO
console.log("TODO: Find team by id ...");
}
function ExtractNewsFromData(data){
// TODO
console.log("TODO: Exctract news from data ...");
}
var GetTeams= function()
{
var zis=this;
var promise = $http({method:"GET",url:"http://www.myserver/teams"});
var successCallback = function(data, status, headers, config) {
var teams = ExtractTeamFromData(data);
return teams;
};
var errorCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
promise.then(successCallback,errorCallback);
return promise;
}
var GetTeam = function(idTeam)
{
var promise = GetTeams();
var successTeamsCallback = function(teams, status, headers, config) {
return FindTeamById(teams, tgeamId);
};
var errorTeamsCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
promise.then(successTeamsCallback,errorTeamsCallback);
return promise;
}
var GetTeamsNews = function(idTeam){
var promise = GetTeam(idTeam);
var successTeamCallback = function(team, status, headers, config) {
var newsPromise = $http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam});
var successNewsCallback = function(data, status, headers, config) {
var news = ExtractNewsFromData(data);
return news;
};
var errorNewsCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
newsPromise.then(successNewsCallback,errorNewsCallback);
return newsPromise;
};
var errorTeamCallback = function(reason, status, headers, config) {
console.error("Some error occured: " + reason);
return {
'errorMessage': reason
};
}
promise.then(successTeamCallback,errorTeamCallback);
return promise;
}
return {
GetTeams: GetTeams,
GetTeam: GetTeam,
GetTeamsNews: GetTeamsNews
};
});
You need to create a promise of your own, and resolve it when done, this way :
return $q(function(resolve, reject) {
$http({method:"GET",url:"http://www.myserver/teams"}).then(function(response){
var promises = [];
for (var i=0;i<response.data.length;i++) {
promises.push(zis.getFavoriteTeamsNews(response.data[i].idTeam)).then(function(newsresponse){
response.data[i].news=newsresponse.data;
});
}
$q.all(promises).then(function(){
resolve(response);
});
});
for (var i=0;i<response.data.length;i++) {
zis.getFavoriteTeamsNews(response.data[i].idTeam).then(function(newsresponse){
response.data[i].news=newsresponse.data;
})
});
I have the following scenario, I need data from a particular url. I have written a function which takes parameter 'url'. Inside the function I have the $http.get method which makes a call to the url. The data is to be returned to the calling function
var getData = function (url) {
var data = "";
$http.get(url)
.success( function(response, status, headers, config) {
data = response;
})
.error(function(errResp) {
console.log("error fetching url");
});
return data;
}
The problem is as follows, $http.get is asynchronous, before the response is fetched, the function returns. Therefore the calling function gets the data as empty string. How do I force the function not to return until the data has been fetched from the url?
Take a look at promises to overcome such issues, because they are used all over the place, in angular world.
You need to use $q
var getData = function (url) {
var data = "";
var deferred = $q.defer();
$http.get(url)
.success( function(response, status, headers, config) {
deferred.resolve(response);
})
.error(function(errResp) {
deferred.reject({ message: "Really bad" });
});
return deferred.promise;
}
Here's a nice article on promises and $q
UPDATE:
FYI, $http service itself returns a promise, so $q is not necessarily required in this scenario(and hence an anti-pattern).
But do not let this be the reason to skip reading about $q and promises.
So the above code is equivalent to following:
var getData = function (url) {
var data = "";
return $http.get(url);
}
You can use $q.all() method also to solve this problem
var requestPromise = [];
var getData = function (url) {
var data = "";
var httpPromise = $http.get(url)
.success( function(response, status, headers, config) {
data = response;
})
.error(function(errResp) {
console.log("error fetching url");
});
requestPromise.push(httpPromise);
}
in the calling function
$q.all(requestPromise).then(function(data) {
//this is entered only after http.get is successful
});
make sure to inject $q as a dependency. Hope it helps
You function seems redundant. Just use $http.get(url), since you aren't really doing anything else before you use it anyway.
var url = 'foo/bar';
$http
.get(url)
.success( function(response, status, headers, config) {
$scope.data = response;
})
.error(function(errResp) {
console.log("error fetching url");
});
Or if you need to access the promise later just assign it to variable;
var promise = $http.get(url);
// some other code..
promise.then(function(data){
//.. do something with data
});
A typical way to do what you want is like so:
var getData = function(url, callback) {
$http.get(url).success(function(response) {
callback && callback(response);
});
};
Used like:
getData('/endpoint', function(data) {
console.log(data);
});
when i console.log(getUserData()) i get Promise {$$state: Object} but how can i retrieve actual value from this returned $$state object so the output be [someArray] or {someObject}..
getUserData = function(){
var defer = $q.defer();
$http.jsonp('http://api.zoopla.co.uk/api/v1/property_listings.js?area='+localData.area_name+'&api_key=xxx&jsonp=someCallback')
someCallback = function(userData){
//console.log(userData);
defer.resolve(userData)
}
return defer.promise;
};
console.log(getUserData())
That function returns promise. So you'll need to handle it properly.
You expect async code to behave syncronously
getUserData = function(){
var defer = $q.defer();
$http.jsonp('http://api.zoopla.co.uk/api/v1/property_listings.js?area='+localData.area_name+'&api_key=xxx&jsonp=someCallback')
someCallback = function(userData){
//console.log(userData);
defer.resolve(userData)
}
return defer.promise;
};
getUserData().then(function (data) {
console.log(data);
});
More about angular deffered and promises: https://docs.angularjs.org/api/ng/service/$q
try this console.log(userData.data);
OR
$http.get('http://api.zoopla.co.uk/api/v1/property_listings.js?area='+localData.area_name+'&api_key=xxx&jsonp=someCallback';
then yourService.getUserData().success(function('success',data){
data
}).
error(function(data, status, headers){status, headers});
On my app, I need to recover data (json) by making multiples validations using http requests before all my app starts. So my problem is that I'm using angular.run() to make all the http requests and resolving all of the validations with promises.
The problem is, not all of my promises are executed before my app is started.
part of my code is:
appModule.run(configRun);
configRun.$inject = [
'$http', '$rootScope', 'gettextCatalog', 'ipLoadDataService',
'webStorageService', 'ipDataSetParserService'];
function configRun($http, $rootScope, gettextCatalog, ipLoadDataSrv, webStrSrv, dataSetParser) {
webStrSrv.clear();
ipLoadDataSrv.getHeadDataSet2()
.then(function (responseHead) {
if (ipLoadDataSrv.updatedDataSet2(responseHead.headers["last-modified"])) {
//save into localstorage
webStrSrv.clear();
webStrSrv.setItem("last-modified", { date: responseHead.headers["last-modified"] });
ipLoadDataSrv.getDataSet2()
.then(function (responseData) {
$rootScope.cabecera = responseData;
})
}
})
}
// LoadDataService
appModule.factory('ipLoadDataService', loadDataService);
loadDataService.$inject = ['$http',
'$q',
'webStorageService',
'myPrjEnvironment',
'ipDataSetParserService'];
function loadDataService($http, $q, webStoreService, myPrj, dataSetParser) {
var eventMap = [];
var ip_loadDataService = {
getHeadDataSet2: getHeadDataSet2,
requestDataSet: requestDataSet,
updatedDataSet2: updatedDataSet2,
getDataSet2: getDataSet2
};
return ip_loadDataService;
function getHeadDataSet2() {
/*HEAD*/
var deferred = $q.defer();
$http.head(myPrj.URL_DATA)
.success(function (data, status, headers, config) {
var response = [];
response.data = data;
response.headers = headers();
deferred.resolve(response);
//return deferred.promise;
}).error(function (data, status) {
deferred.reject(data);
});
return deferred.promise;
}
function getDataSet2() {
return xhr('get', [myPrj.URL_DATA]);
}
function updatedDataSet2(last_date_modified) {
//var self = this;
var dateOnWebStore = webStoreService.getItem("last-modified");
if (dateOnWebStore === null || Date.parse(dateOnWebStore.date) < Date.parse(last_date_modified))
return true;
return false;
}
function xhr(type, config) {
if (!config && angular.isArray(type)) {
config = type;
type = 'get';
}
var deferred = $q.defer();
$http[type].apply($http, config)
.success(function (data, status, headers, config) {
var response = [];
response.data = data;
response.headers = headers();
deferred.resolve(response);
})
.error(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
}
Answering the question in your second post, maybe you better edit your original post with the new issue you encountered.
If what you are looking for is a way to activate a state (home.myPrjMain in your case) you can do this in various ways:
Using JS - use $state.go(). See - $State documentation
Using directive - use the ui-sref directive with the name of the required state. See - ui-sref documentation
Using regular html href (Navigate to url) - with the full address of the state you need. In your case, "/main".
I hope this was helpful
Have the UI start in an initial loading state then use ui-router to wait for the various pieces to resolve before going to the initial state.
Here is a fiddle showing how it works. Fiddle
I did two parts, one with a single fake service call using timeout and a second with a chained set of calls,.
this.slowServiceCall = function(input, delay) {
var deferred = $q.defer();
var workFinished = function () {
deferred.resolve(input);
};
$timeout(workFinished, delay);
return deferred.promise;
};
this.slowChainedServiceCall = function(input, delay) {
var deferred = $q.defer();
var workFinished = function () {
deferred.resolve(input);
};
$timeout(workFinished, delay);
var promiseChain = deferred.promise.then(function(result) {
var deferred2 = $q.defer();
$timeout(function(){
deferred2.resolve(result + ' Second Piece');
},100);
return deferred2.promise;
});
return promiseChain;
};