Then is not a function error in angularjs - angularjs

I have simple function which returns employee data. But getting then is not a function error how to retrieve response from function
function getdata(criteria) {
return angularService.GetData(criteria, $scope.year, $scope.selectedYearType.name);
}
Which is called in below function
$scope.GetEmployeeData = function (criteria) {
$scope.searchMethod = getdata;
$scope.searchMethod().then(function (response) {----------> Error here
var totalEmployeeAmount = 0;
for (var i = 0; i < response.data.results.length; i++) {
var summaryData = response.data.results[i];
totalEmployeeAmount += (summaryData.totalEmployeeAmount);
}
return response
}, function (response) {
// This is to see if has any error
//console.log(response);
});
}
My angular service
function getData(criteria, year, yearType) {
var url = apiService.ApiUrl + "/Employees/EmployeeHistory/GetData/" + year + "/" + yearType;
return apiService.DeferredPost(url, criteria);}
Deferred Post Method
function deferredPost(url, params) {
var deferred = $q.defer();
$http.post(url, params)
.then(function (data) {
deferred.resolve(data);
}, function (resp) {
deferred.reject(resp);
}).catch(function (data) {
deferred.reject(data);
});
return deferred.promise;
}
API
var api = {
DeferredPost: deferredPost
};
return api;

Should be calling .then on searchMethod instead of searchMethod() - assuming getdata returns a promise as you can't call .then on a function that doesn't return a promise. Also I'm guessing you should be passing in the criteria as a parameter to getdata:
$scope.GetEmployeeData = function (criteria) {
$scope.searchMethod = getdata;
$scope.searchMethod.then(function (response) {
var totalEmployeeAmount = 0;
for (var i = 0; i < response.data.results.length; i++) {
var summaryData = response.data.results[i];
totalEmployeeAmount += (summaryData.totalEmployeeAmount);
}
return response
}, function (response) {
// This is to see if has any error
//console.log(response);
});
}

As #William Hampshire said, you should be using $scope.searchMethod.then(function ... ) instead of $scope.searchMethod().then(function ... )
$scope.GetEmployeeData = function (criteria) {
$scope.searchMethod = getdata(criteria);
$scope.searchMethod.then(function (response) {
var totalEmployeeAmount = 0;
for (var i = 0; i < response.data.results.length; i++) {
var summaryData = response.data.results[i];
totalEmployeeAmount += (summaryData.totalEmployeeAmount);
}
return response
}, function (response) {
// This is to see if has any error
//console.log(response);
});
}
The reason why your code is still failing is that you have a typo in your service name.
function getdata(criteria) {
return angularService.GetData(criteria, $scope.year, $scope.selectedYearType.name);
}
It should be GetData instead of getData.
function GetData(criteria, year, yearType) {
var url = apiService.ApiUrl + "/Employees/EmployeeHistory/GetData/" + year + "/" + yearType;
return apiService.DeferredPost(url, criteria);}

Related

angular multiple http looping request with time delay

I have an ID array contains with 50+ id.
var ids = [
'3407197',
'0632706',
'18275',
...,
...
]
I want to send angular HTTP get request with a loop. Each iteration will delay 10 sec delay. When all the request complete it will notify that request are completed.
I have tried with this code but It executes at once not delaying.
function collector(i){
setTimeout(function() {
return $http.get('http://example.com/' + ids[i])
.success(function(data) {
})
.error(function(err) {
})
},10000);
}
$scope.getAllData = function() {
var promises = [];
for (var i = 0; i < ids.length; i++) {
promises.push(collector(i));
}
return $q.all(promises);
}
$scope.getAllData ().then(function(data) {
$scope.debug = 'done';
});
Try with $timeout:
function getRequest(id) {
return $http.get('http://example.com/' + id)
.success(function (data) {})
.error(function (err) {});
}
var promise = $timeout();
ids.forEach(function(id) {
promise = promise.then(function() {
getRequest(id);
return $timeout(10000);
});
});
// not sure if this works
promise.then(function() {
$scope.debug = 'done';
});

Declare a function inside another function

i have this function:
charCtrl.loadDataFromToMonth= function (from,to,year) {
var url = servername+'admin/dashboard/getIncidentDepartByMonthFromTo/'+from+'/'+to+'/'+year;
//alert(url);
function onSuccess(response) {
console.log("+++++getIncidentDepartByMonthFromTo SUCCESS++++++");
if (response.data.success != false) {
$scope.payloadgetIncidentDepartByMonthFromTo = response.data.data;
var getIncidentDepartByMonthFromTo= $scope.payloadgetIncidentDepartByMonthFromTo;
// alert('dddd'+JSON.stringify(loadedDataByMission));
$scope.labelsf = [];
$scope.qsd = [];
$scope.dataf = [];
getIncidentDepartByMonthFromTo.forEach(function(data) {
var monthNumber=$filter('date')(data.la_date, "MM");
$scope.labelsf.push($filter('monthName')(monthNumber));
$scope.dataf.push(data.number);
$scope.qsd.push('ff','ff','ff');
//alert($scope.labelsf );
});
//alert( $scope.dataf );
charCtrl.loadDataFromToMonthArrivee(from,to,year);
} else {
alert("failure");
}
// $scope.stopSpin('spinner-0');
};
function onError(response) {
console.log("-------getIncidentDepartByMonthFromTo FAILED-------");
//$scope.stopSpin('spinner-0');
console.log(response.data);
console.log("Inside getIncidentDepartByMonthFromTo error condition...");
};
//----MAKE AJAX REQUEST CALL to GET DATA----
ajaxServicess.getData(url,username,password, 'GET', '').then(onSuccess, onError);
};
this function return for exemple: $scope.dataf = ['45','48','255'];
I have a second function, by the way its the same function but it gets data from other Rest service:
charCtrl.loadDataFromToMonthArrivee= function (from,to,year) {
var url = servername+'admin/dashboard/getIncidentArriveeByMonthFromTo/'+from+'/'+to+'/'+year;
//alert(url);
function onSuccess(response) {
console.log("+++++getIncidentDepartByMonthFromTo SUCCESS++++++");
if (response.data.success != false) {
$scope.payloadgetIncidentArriveeByMonthFromTo = response.data.data;
var getIncidentArriveeByMonthFromTo= $scope.payloadgetIncidentArriveeByMonthFromTo;
// alert('dddd'+JSON.stringify(loadedDataByMission));
$scope.labelsf = [];
$scope.qsd = [];
$scope.dataf = [];
getIncidentArriveeByMonthFromTo.forEach(function(data) {
var monthNumber=$filter('date')(data.la_date, "MM");
$scope.labelsf.push($filter('monthName')(monthNumber));
$scope.dataf.push(data.number);
//$scope.qsd.push('ff','ff','ff');
//alert($scope.labelsf );
});
alert('aqsz'+$scope.dataf );
} else {
alert("failure");
}
// $scope.stopSpin('spinner-0');
};
function onError(response) {
console.log("-------getIncidentDepartByMonthFromTo FAILED-------");
//$scope.stopSpin('spinner-0');
console.log(response.data);
console.log("Inside getIncidentDepartByMonthFromTo error condition...");
};
//----MAKE AJAX REQUEST CALL to GET DATA----
ajaxServicess.getData(url,username,password, 'GET', '').then(onSuccess, onError);
};
this function return for exemple: $scope.dataf = ['69','50','96'];
my question is: is there a way to declare the second function in the first fuction and get a result like this:
this function return for exemple: $scope.dataf = [['45','48','255'],['69','50','96']];
I would use promises to wait for the second call to respond and update a variable in the function scope (sibling to the function). Something like this:
var aggregate = [];
charCtrl.loadDataFromToMonth()
.then(function(resp){
return new Promise(resolve, reject){
aggregate.push(resp.data); // push the response from the first call
charCtrl.loadDataFromToMonthArrivee()
.then(function(resp) {
aggregate.push(resp.data); // push the result from the second call
resolve(resp)
})
}
})
.then(function(resp){
console.log(aggregate); // should have both results
})
Or better yet, you can use Promise.all (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)

Angular Promise - $q.all not returning result and calling Post method several times not working

Am trying to call a Post method and then depending on the result I am going to call same Post method multiple times and return the result, using $q.all.
My Post method is :
getData: function (params, callback) {
$http.post('service/myService', params)
.success(function (data) {
callback(null, data);
}).error(function (error) {
callback(error);
});
}
I am calling it in below function, this function is recursive so if it contains nextUrl I am doing same thing until there is no object for paging:
var result = [];
var promises = [];
var checkForPaging = function (nextUrl, service, $q) {
var deferred = $q.defer();
var criteria = {
url: url
}
var promise = service.getData(criteria, function (error, data) {
if (data.statusCode == 200) {
for (var i = 0; i < data.body.items.length; i++) {
result.push(data.body.items[i]);
}
if (data.body.paging != null && data.body.paging.next != null) {
checkForPaging(data.body.paging.next.url, service, $q);
} else{
deferred.resolve(result);
}
}
});
promises.push(promise);
$q.all(promises)
return deferred.promise;
}
Then am calling this function from below and want to get the result back once all calls are complete:
checkForPaging(data.body.paging.next.url, myService, $q).then(function (data) {
console.log(data)
});
The issue I am having is that it never hits the callback function above : console.log(data). But I can see it calling the Post method several times.
If I resolve it like below then I can see after first Post it is hitting the callback above:
$q.all(promises).then(function (results) {
deferred.resolve(result);
}, function (errors) {
deferred.reject(errors);
});
Am I doing it right? How can I get the result back and call the Post method several times?
Let me know if it is not clear or have any questions!
Try something like this with proper promise chaining:
var result = [];
var checkForPaging = function(nextUrl, service) {
var criteria = {
url: url
}
return service.getData(criteria, function(error, data) {
if (data.statusCode == 200) {
for (var i = 0; i < data.body.items.length; i++) {
result.push(data.body.items[i]);
}
if (data.body.paging != null && data.body.paging.next != null) {
return checkForPaging(data.body.paging.next.url, service);
} else {
return result;
}
}
});
}
checkForPaging(data.body.paging.next.url, myService).then(function(data) {
console.log(data)
});
And getData:
getData: function(params) {
return $http.post('service/myService', params)
.then(function(response) {
return response.data;
});
}
Here is solution: https://plnkr.co/edit/HqkFNo?p=preview I rewrited logic a bit.
You can catch the main idea.
UPDATE added promiseless solution
1) Your service should return only promise:
this.getData = function(url, params){
return $http.post(url, params); //You're just returning promise
}
2) You don't need $q.all, you can use single promise:
var result = [];
var deferred;
var checkForPaging = function (url) {
if(!deferred){
deferred = $q.defer();
}
//resolvind service promise
newService.getData(url).then(
//if ok - 200
function(response){
for (var i = 0; i < data.body.items.length; i++) {
result.push(data.body.items[i]);
}
if (data.body.paging != null && data.body.paging.next != null){
{
return checkForPaging(data.body.paging.next.url);
} else{
deferred.resolve(result);
}
},
//handle errors here
function(error) {
}
);
return deferred.promise;
}
3) You should call it like this:
checkForPaging('url').then(function(data){
//here will be resolved promise
console.log(data);
});

How to get email address from twitter

The twitter login is used by my app using ionic framework, and i want to get email address from twitter, i have requested twitter and app is now able to get email address.
But somehow the code below is not able to get email address.
For this i have created new function named getTwitterProfileManual but still it is not working.
I have also read document provided by twitter at Doc and as suggested i am also passing include_email params as request query. But still response do not have email address in it.
serviceModule.factory('TwitterService', function ($cordovaOauth, $cordovaOauthUtility, $http, $resource, $q, AUTH_ID)
{
var twitterKey = "STORAGE.TWITTER.KEY";
var clientId = AUTH_ID.TWITTER_APP_ID;
var clientSecret = AUTH_ID.TWITTER_APP_SEC;
function storeUserToken(data)
{
window.localStorage.setItem(twitterKey, JSON.stringify(data));
}
function getStoredToken()
{
return window.localStorage.getItem(twitterKey);
}
function createTwitterSignature(method, url, params)
{
if (!params) {
params = {};
}
var token = angular.fromJson(getStoredToken());
var oauthObject = {
oauth_consumer_key: clientId,
oauth_nonce: $cordovaOauthUtility.createNonce(10),
oauth_signature_method: "HMAC-SHA1",
oauth_token: token.oauth_token,
oauth_timestamp: Math.round((new Date()).getTime() / 1000.0),
oauth_version: "1.0"
};
console.log(JSON.stringify(oauthObject));
var signatureObj = $cordovaOauthUtility.createSignature(method, url, oauthObject, params, clientSecret, token.oauth_token_secret);
$http.defaults.headers.common.Authorization = signatureObj.authorization_header;
console.log(JSON.stringify(signatureObj.authorization_header));
}
return {
initialize: function ()
{
var deferred = $q.defer();
var token = getStoredToken();
if (token !== null)
{
deferred.resolve(true);
}
else
{
$cordovaOauth.twitter(clientId, clientSecret).then(function (result)
{
storeUserToken(result);
deferred.resolve(true);
}, function (error)
{
deferred.reject(false);
});
}
return deferred.promise;
},
isAuthenticated: function ()
{
return getStoredToken() !== null;
},
getHomeTimeline: function ()
{
var home_tl_url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
createTwitterSignature('GET', home_tl_url);
return $resource(home_tl_url).query();
},
getTwitterProfile: function ()
{
var tl_url = 'https://api.twitter.com/1.1/account/verify_credentials.json';
createTwitterSignature('GET', tl_url);
return $resource(tl_url, {'include_email': true}).query();
},
getTwitterProfileManual: function () {
var deferred = $q.defer();
var token = angular.fromJson(getStoredToken());
createTwitterSignature('GET', 'https://api.twitter.com/1.1/account/verify_credentials.json');
// $http.get("https://api.twitter.com/1.1/account/verify_credentials.json")
$http({
method: 'GET',
url: "https://api.twitter.com/1.1/account/verify_credentials.json",
params : { 'include_email': true }
}).success(function (result)
{
console.log(result);
alert('USER TIMELINE: ' + JSON.stringify(result));
deferred.resolve(result);
}).error(function (error)
{
alert("Error: " + JSON.stringify(error));
deferred.reject(false);
});
return deferred.promise;
},
storeUserToken: storeUserToken,
getStoredToken: getStoredToken,
createTwitterSignature: createTwitterSignature
};
});
Does anyone came across such problem and solved it, if so please provide some hint.
After days of working i finally made it working.
Below is the code for anyone who will face such issue.
Code :
serviceModule.factory('$twitterHelpers', ['$q', '$http', function ($q, $http) {
function createSignature(method, endPoint, headerParameters, bodyParameters, secretKey, tokenSecret) {
if (typeof jsSHA !== "undefined") {
var headerAndBodyParameters = angular.copy(headerParameters);
var bodyParameterKeys = Object.keys(bodyParameters);
for (var i = 0; i < bodyParameterKeys.length; i++) {
headerAndBodyParameters[bodyParameterKeys[i]] = escapeSpecialCharacters(bodyParameters[bodyParameterKeys[i]]);
}
var signatureBaseString = method + "&" + encodeURIComponent(endPoint) + "&";
var headerAndBodyParameterKeys = (Object.keys(headerAndBodyParameters)).sort();
for (i = 0; i < headerAndBodyParameterKeys.length; i++) {
if (i == headerAndBodyParameterKeys.length - 1) {
signatureBaseString += encodeURIComponent(headerAndBodyParameterKeys[i] + "=" + headerAndBodyParameters[headerAndBodyParameterKeys[i]]);
} else {
signatureBaseString += encodeURIComponent(headerAndBodyParameterKeys[i] + "=" + headerAndBodyParameters[headerAndBodyParameterKeys[i]] + "&");
}
}
var oauthSignatureObject = new jsSHA(signatureBaseString, "TEXT");
var encodedTokenSecret = '';
if (tokenSecret) {
encodedTokenSecret = encodeURIComponent(tokenSecret);
}
headerParameters.oauth_signature = encodeURIComponent(oauthSignatureObject.getHMAC(encodeURIComponent(secretKey) + "&" + encodedTokenSecret, "TEXT", "SHA-1", "B64"));
var headerParameterKeys = Object.keys(headerParameters);
var authorizationHeader = 'OAuth ';
for (i = 0; i < headerParameterKeys.length; i++) {
if (i == headerParameterKeys.length - 1) {
authorizationHeader += headerParameterKeys[i] + '="' + headerParameters[headerParameterKeys[i]] + '"';
} else {
authorizationHeader += headerParameterKeys[i] + '="' + headerParameters[headerParameterKeys[i]] + '",';
}
}
return {signature_base_string: signatureBaseString, authorization_header: authorizationHeader, signature: headerParameters.oauth_signature};
} else {
return "Missing jsSHA JavaScript library";
}
}
function createNonce(length) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
function escapeSpecialCharacters(string) {
var tmp = encodeURIComponent(string);
tmp = tmp.replace(/\!/g, "%21");
tmp = tmp.replace(/\'/g, "%27");
tmp = tmp.replace(/\(/g, "%28");
tmp = tmp.replace(/\)/g, "%29");
tmp = tmp.replace(/\*/g, "%2A");
return tmp;
}
function transformRequest(obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + escapeSpecialCharacters(obj[p]));
console.log(str.join('&'));
return str.join('&');
}
return {
createTwitterSignature: function (method, url, bodyParameters, clientId, clientSecret, token) {
var oauthObject = {
oauth_consumer_key: clientId,
oauth_nonce: createNonce(10),
oauth_signature_method: "HMAC-SHA1",
oauth_token: token.oauth_token,
oauth_timestamp: Math.round((new Date()).getTime() / 1000.0),
oauth_version: "1.0"
};
var signatureObj = createSignature(method, url, oauthObject, bodyParameters, clientSecret, token.oauth_token_secret);
$http.defaults.headers.common.Authorization = signatureObj.authorization_header;
return signatureObj;
},
transformRequest: transformRequest
};
}]);
serviceModule.factory('TwitterService', function ($cordovaOauth, $cordovaOauthUtility, $http, $resource, $q, AUTH_ID, $twitterHelpers)
{
var twitterKey = "STORAGE.TWITTER.KEY";
var clientId = AUTH_ID.TWITTER_APP_ID;
var clientSecret = AUTH_ID.TWITTER_APP_SEC;
function storeUserToken(data)
{
window.localStorage.setItem(twitterKey, JSON.stringify(data));
}
function getStoredToken()
{
return window.localStorage.getItem(twitterKey);
}
return {
initialize: function ()
{
var deferred = $q.defer();
var token = getStoredToken();
if (token !== null)
{
deferred.resolve(true);
}
else
{
$cordovaOauth.twitter(clientId, clientSecret).then(function (result)
{
storeUserToken(result);
deferred.resolve(true);
}, function (error)
{
deferred.reject(false);
});
}
return deferred.promise;
},
isAuthenticated: function ()
{
return getStoredToken() !== null;
},
getHomeTimeline: function ()
{
var home_tl_url = 'https://api.twitter.com/1.1/statuses/home_timeline.json';
createTwitterSignature('GET', home_tl_url);
return $resource(home_tl_url).query();
},
getTwitterProfileManual: function () {
var deferred = $q.defer();
var token = angular.fromJson(getStoredToken());
$twitterHelpers.createTwitterSignature('GET', 'https://api.twitter.com/1.1/account/verify_credentials.json', { 'include_email' : 'true' }, clientId, clientSecret, token);
$http({
method: 'GET',
url: "https://api.twitter.com/1.1/account/verify_credentials.json",
params: {'include_email': 'true'},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (result)
{
console.log(result);
alert('USER TIMELINE: ' + JSON.stringify(result));
deferred.resolve(result);
}).error(function (error)
{
alert("Error: " + JSON.stringify(error));
deferred.reject(false);
});
return deferred.promise;
},
storeUserToken: storeUserToken,
getStoredToken: getStoredToken
};
});
From the above code use getTwitterProfileManual this function to get email address in twitter user object response.
Note : To get email address your twitter app must be whitelisted to have access to user email address.

Angular callback when multiple http are done

How do I create 1 callback function for multiple http in angularjs. My code:
for (var i = 0; i < docs.length; i++) {
this.base64(docs[i], function(base64Img){
$http.post(urls.BASE + '/store',{doc:base64Img}).then(
function(result) {
console.log(result);
}
);
});
}
mycallback.call(); <-- this should be done when all my http.post above are done.
Use $q.all():
var deferred = $q.defer();
var httpPromises = [];
for (var i = 0; i < docs.length; i++) {
this.base64(docs[i], function(base64Img) {
httpPromises.push($http.post(urls.BASE + '/store',{doc:base64Img});
if (httpPromises.length === docs.length) {
deferred.resolve();
}
}));
}
return deferred.promise.then(function() {
return $q.all(httpPromises);
});
Note that if this.base64() returned a promise rather than taking a callback in argument, that would be simpler:
var promises = [];
for (var i = 0; i < docs.length; i++) {
promises.push(this.base64(docs[i]).then(function(base64Img) {
return $http.post(urls.BASE + '/store',{doc:base64Img});
}));
}
return $q.all(promises);
or even
return $q.all(docs.map(function(doc) {
return this.base64(doc).then(function(base64Img) {
return $http.post(urls.BASE + '/store',{doc:base64Img});
});
});
Okay so I created a HttpInterceptor Service for this so every time a request starts it checks if there are more requests within a certain timelimit and then after all of those requests responded It broadcasts "all requests done".
For that to work I embeded my Intercepter like this in my App.js
.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
})
And my service looks like this basicly there is a variable numloadings which counts the requests up and when there is a respones it counts them down when it reaches 0 all requests went through
.factory('httpInterceptor', ['$q', '$rootScope', '$filter', function ($q, $rootScope, $filter) {
var canceller = $q.defer();
var numLoadings = 0;
var serialRequests = false;
var timeO;
var time1;
var Cntr1 = 0;
var Cntr2 = 0;
var currentReqUrl;
$rootScope.broadcast = true;
var loadingbar = { loading: "<progress value='?' max='10'></progress>" };
var loadingspinner = { loading: '<ion-spinner icon="crescent"></ion-spinner>' };
return {
request: function (config) {
config.timeout = 200000;
numLoadings++;
if (serialRequests == false) {
$rootScope.$broadcast("open_requests", loadingspinner);
} else {
clearTimeout(timeO);
}
}
return config || $q.when(config)
},
response: function (response) {
serialRequests = true;
numLoadings--;
timeO = setTimeout(function () {
serialRequests = false
if ((numLoadings) === 0) {
$rootScope.$broadcast("all_requests_done");
}
});
}
return response || $q.when(response);
},
responseError: function (response) {
serialRequests = true;
numLoadings--;
timeO = setTimeout(function () {
serialRequests = false
if ((numLoadings) === 0) {
$rootScope.$broadcast("all_requests_done");
}
});
}
return $q.reject(response);
}
};

Resources