Problems understanding the AngularJS promise API - AuthenticationService - javascript

Good evening everybody. I startet creating a mobile application with AngularJS,Ionic & Cordova some weeks ago. I try to create a AuthenticationService for this app using a given API.
I checked some tutorials and created this and it seems to work besides the promise handling. I have got a deficit there.
Maybe someone good help me :)
Here i handle the access to certain pages/states.
$rootScope.$on('$stateChangeStart', function (event, next, nextParams, fromState) {
if ('data' in next && 'authorizedRoles' in next.data) {
var authorizedRoles = next.data.authorizedRoles;
if (!AuthService.isAuthorized(authorizedRoles)) {
event.preventDefault();
$state.go($state.current, {}, {
reload: true
});
$rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
}
}
if (next.name == 'app.admin' || next.name == 'app.bonus') {
AuthService.isAuthenticated().then(function (response) {
}, function (response) {
var alertPopup = $ionicPopup.alert({
title: 'Error1!',
template: 'Sorry, You have to login again.'
});
event.preventDefault();
$state.go('app.login');
$log.log(response + '1er');
});
}
});
Here I perform the user-login
.controller('LoginCtrl', function ($scope, $ionicPopup, AuthService, $state, $log, $q) {
$scope.data = {};
$scope.login = function (data) {
$q.all([
AuthService.login(data.username, data.password),
AuthService.isAuthenticated()
]).then(function (data) {
console.log(data[0]);
console.log(data[1]);
if (data[0] == false) {
var alertPopup = $ionicPopup.alert({
title: 'Error!',
template: 'Sorry, You have to login again.'
});
}
if (data[1] == true) {
$state.go('app.bonus', {}, {
reload: true
});
} else {
var alertPopup = $ionicPopup.alert({
title: 'Error!',
template: 'Sorry, You have to login again.'
});
}
});
};
})
Here I created the service handling the user-role, validation & creation of the cookie - Every API-call needs a nonce which is created also
.service('AuthService', function ($q, $http, USER_ROLES, $log) {
var link = 'http://example/api/';
var username = '';
var isAuthenticated = false;
var role = '';
var mycookie = '';
var mynonce = '';
function checkCookie() {
mycookie = window.localStorage.getItem('LOCAL_COOKIE');
$log.info(mycookie);
if (mycookie) {
$http.get(link + 'get_nonce/?controller=user&method=generate_auth_cookie&insecure=cool').then(
function (result) {
if (result.data.status == "ok") {
mynonce = result.data.nonce;
$log.info(mynonce);
} else {
return false;
}
},
function (err) {
return false;
});
$http.get(link + 'user/validate_auth_cookie/?cookie=' + mycookie + '&nonce=' + mynonce + '&insecure=cool').then(
function (result) {
if (result.data.status == "ok") {
return true;
} else {
window.localStorage.removeItem('LOCAL_COOKIE');
return false;
}
},
function (err) {
return false;
});
} else {
return false;
}
}
function doLogin(name, pw) {
var loginAttempt = false;
$http.get(link + 'get_nonce/?controller=user&method=generate_auth_cookie&insecure=cool').then(
function (result) {
if (result.data.status == "ok") {
mynonce = result.data.nonce;
$log.info(mynonce);
} else {
loginAttempt = false;
}
},
function (err) {
loginAttempt = false;
$log.info(err);
});
mycookie = $http.get(link + 'user/generate_auth_cookie/?username=' + encodeURIComponent(name) + '&password=' + encodeURIComponent(pw) + '&nonce=' + mynonce + '&insecure=cool').then(
function (result) {
if (result.data.status == "ok") {
mycookie = result.data.cookie;
loginAttempt = true;
username = name;
if (username == 'MarkusK') {
role = USER_ROLES.admin
} else {
role = USER_ROLES.public
}
window.localStorage.setItem('LOCAL_COOKIE', mycookie);
$log.info(mycookie);
} else {
loginAttempt = false;
}
},
function (err) {
loginAttempt = false;
$log.info(err);
});
$log.info('test1' + loginAttempt);
return loginAttempt;
};
var login = function (name, pw) {
return $q(function (resolve, reject) {
if (doLogin(name, pw)) {
resolve('Login success.');
} else {
reject('Login Failed.');
}
});
};
var validCookie = function () {
return $q(function (resolve, reject) {
if (checkCookie()) {
resolve('Cookie success.');
} else {
reject('Cookie Failed.');
}
});
};
var logout = function () {
mycookie = undefined;
username = '';
isAuthenticated = false;
window.localStorage.removeItem('LOCAL_COOKIE');
};
var isAuthorized = function (authorizedRoles) {
if (!angular.isArray(authorizedRoles)) {
authorizedRoles = [authorizedRoles];
}
return (checkCookie() && authorizedRoles.indexOf(role) !== -1);
};
return {
login: login,
logout: logout,
isAuthorized: isAuthorized,
isAuthenticated: validCookie,
username: function () {
return username;
},
role: function () {
return role;
}
};
})
Maybe someone got time to help me and I finally understand the promise API.
Thank you.

You have a nice illustrated definition here:
http://andyshora.com/promises-angularjs-explained-as-cartoon.html.
Let' say we have the following code (isn't meaning anything it's only to explain the promise concept):
var a = 1;
a = foo();
a = a + 2;
Because JavaScript is asynchronous, the second instruction (the call to foo()), won't block the thread.
if foo() is waiting for other ressource (value from a server), it won't wait and will get into the third instruction (a = 2).
The promise is used to tell JavaScript thread: "Hey don't forget to comeback when I'll be ready, you promised me :)".

Related

"Uncaught TypeError: Cannot read property 'defer' of undefined at Websocket Angular JS"

I am pretty new to web technologies, I got bits & pieces of code from internet and somehow managed to form this code.
I have to get data to a web app developed in angularjs from websocket through APIs.
here is the code,
angular.module("MyApp")
.service("myService", function ($rootScope, $q) {
return {
_prevTransmittingStatus: null,
transmitting: false,
_transmissionStatus: function () {},
socket: null,
socket_msg_id: 0,
socket_history: {},
url: "ws://localhost:4848/app/",
setOnTransmissionStatus: function (callback) {
var self = this;
this._transmissionStatus = function () {
if (self.transmitting != self._prevTransmittingStatus) {
self._prevTransmittingStatus = self.transmitting
callback(self.transmitting)
} else {}
}
},
connect: function (callback) {
var deferred = $q.defer();
var promise = deferred.promise;
var self = this
this.transmitting = true;
this._transmissionStatus();
this.socket = new WebSocket(this.url);
this.socket.addEventListener('open', function (e) {
self.transmitting = false;
self._transmissionStatus();
deferred.resolve("connected")
});
this.socket.addEventListener('message', function (e) {
var asJson = angular.fromJson(e.data)
var replyId = asJson.id;
var histItem = self.socket_history[replyId]
self.transmitting = false;
self._transmissionStatus();
if (angular.isUndefined(asJson.error)) {
$rootScope.$apply(histItem.defer.resolve(asJson.result))
} else {
**GetActiveDoc();/*how to call this */**
console.log("---rejected-----");
$rootScope.$apply(histItem.defer.reject(asJson.error))
}
});
return promise;
},
disconnect: function () {
this.socket.close();
this.transmitting = false;
this._transmissionStatus();
return this;
},
send: function (msg, scope, callback, onerror) {
console.info("SEND:", msg)
var _this = this;
this.transmitting = true;
this._transmissionStatus();
if (!this.socket) {
return this.connect().then(
function (histItem) {
console.log("CONNECT SUCCESS", histItem)
},
function (histItem) {
console.log("CONNECT ERROR", histItem)
}
).then(function () {
return _this.send(msg, scope);
})
} else if (this.socket) {
console.log("socket is open")
var deferred = $q.defer();
var promise = deferred.promise;
msg.id = this.socket_msg_id;
this.socket_history[msg.id] = {
id: msg.id,
defer: deferred,
scope: scope,
msg: msg
};
this.socket_msg_id++
this.socket.send(angular.toJson(msg))
return promise
}
},
isConnected: function () {
return this.socket ? true : false;
}
}
});
I am getting an error "Uncaught TypeError: Cannot read property 'defer' of undefined at Websocket" only for the first time when I open my web app.
Can some one explain how to resolve this.
solved it myself, just added/modified the code as follows,
if(replyId >= 0){
$rootScope.$apply(histItem.defer.resolve(asJson.result))
}

Callback return empty array js

Here is the function with in sql queries call.
I need return callback only after all queries done.
But it return an empty array
How to return array with data after all?
`
function getUserSales(days, callback){
getUserByLastLoginDay(days, function (users) {
var userArray = [];
_.each(users, function (user) {
getMostFavoredCat(user.id, function (cat) {
if(!cat || cat.length == 0){
return false;
} else {
user.mostFavoredCat = takeMostRepeatingObj(cat);
}
getRelatedSaleByCat(user.id, user.mostFavoredCat.id, function (sales) {
user.sales = sales;
userArray.push(user)
})
})
})
callback(userArray);
})
}
`
callback function first parameter is always an error
callback(null,userArray)
you can make use of async.js for the better control flow
npm i async --save
const async = require('async');
function getUserSales(days, callback){
getUserByLastLoginDay(days, function (users) {
var userArray = [];
async.each(users, function (user, cb) {
getMostFavoredCat(user.id, function (cat) {
if(!cat || cat.length == 0){
return false;
} else {
user.mostFavoredCat = takeMostRepeatingObj(cat);
}
getRelatedSaleByCat(user.id, user.mostFavoredCat.id, function (sales) {
user.sales = sales;
userArray.push(user)
cb();
})
})
}, (err) => {
if (err) {
return callback(err);
} else {
callback(null, userArray);
}
})
})
}
I think it will Works:
function getUserSales(days, callback){
getUserByLastLoginDay(days, function (users) {
var userArray = [];
_.each(users, function (user) {
getMostFavoredCat(user.id, function (cat) {
if(!cat || cat.length == 0){
return false;
} else {
user.mostFavoredCat = takeMostRepeatingObj(cat);
}
getRelatedSaleByCat(user.id, user.mostFavoredCat.id, function (sales) {
user.sales = sales;
userArray.push(user)
})
})
callback(userArray);
})
})
}

Angular $q nested promise

I have a function that needs to return a list of favorite locations. Something like this
LocationsFactory.getFavoriteLocations().then(function($favoriteLocations) {
});
The getFavoriteLocations looks something like this
getFavoriteLocations: function() {
if (favorite_locations.length == 0)
{
var deff = $q.defer();
obj.getDeviceId().then(function(device_id) {
$http.get('url?token=' + device_id).then(function(response) {
favorite_locations = response.data;
deff.resolve(favorite_locations);
return deff.promise;
})
})
} else {
return favorite_locations;
}
}
The getDeviceId again, it's a function based on promise.
getDeviceId: function() {
var deff = $q.defer();
deff.resolve(Keychain.getKey());
return deff.promise;
}
The error that I got is TypeError: Cannot read property 'then' of undefined. Please help!
You can chain promises:
getFavoriteLocations: function () {
if (favorite_locations.length === 0) {
return obj.getDeviceId().then(function (device_id) {
return $http.get('url?token=' + device_id).then(function (response) {
favorite_locations = response.data;
return favorite_locations;
});
});
}
return $q.resolve(favorite_locations);
}
And improve this:
getDeviceId: function() {
return $q.resolve(Keychain.getKey());
}
$q in not necessary here:
if (favorite_locations.length == 0)
{
return obj.getDeviceId() // you have to return a promise here
.then(function(device_id) {
return $http.get('url?token=' + device_id) // you will access the response below
})
.then(function(response) {
favorite_locations = response.data;
return favorite_locations
});
})
}
Now it should work.

Reformatting for Angular style guide 1.5

I am using the Angular spyboost utility wrapper. I am trying to reformat it for this angular 1 style guide. I'm having a hard time with parts of it. I think I have most of it correct but the angular.forEach function is throwing me off. I am and am getting an error `Expected '{' and instead saw 'result'. Could someone help me please ?
angular
.module('myMod')
.factory('MyService');
MyService.$inject = ['$rootScope', 'atmosphereService', 'atmosphere'];
function MyService ($rootScope, atmosphere) {
return {
subscribe: subscribe,
getMessage: getMessage
};
function subscribe (r) {
var responseParameterDelegateFunctions = ['onOpen', 'onClientTimeout', 'onReopen', 'onMessage', 'onClose', 'onError'];
var delegateFunctions = responseParameterDelegateFunctions;
var result = {};
delegateFunctions.push('onTransportFailure');
delegateFunctions.push('onReconnect');
angular.forEach(r, function (value, property) {
if (typeof value === 'function' && delegateFunctions.indexOf(property) >= 0) {
if (responseParameterDelegateFunctions.indexOf(property) >= 0)
**result[property] = function (response) {**
$rootScope.$apply(function () {
r[property](response);
});
};
else if (property === 'onTransportFailure')
result.onTransportFailure = function (errorMsg, request) {
$rootScope.$apply(function () {
r.onTransportFailure(errorMsg, request);
});
};
else if (property === 'onReconnect')
result.onReconnect = function (request, response) {
$rootScope.$apply(function () {
r.onReconnect(request, response);
});
};
} else
result[property] = r[property];
});
function getMessage () {
var vm = this;
var request = {
url: '/chat',
contentType: 'application/json',
transport: 'websocket',
reconnectInterval: 5000,
enableXDR: true,
timeout: 60000
};
request.onMessage(response); {
vm.$apply (function () {
vm.model.message = atmosphere.util.parseJSON(response.responseBody);
});
}
}
return atmosphere.subscribe(result);
}
}
})(window.angular);
if (responseParameterDelegateFunctions.indexOf(property) >= 0)
is missing its curly braces?
if (responseParameterDelegateFunctions.indexOf(property) >= 0) {
result[property] = function (response) {
$rootScope.$apply(function () {
r[property](response);
});
};
}
else if (property === 'onTransportFailure') {
result.onTransportFailure = function (errorMsg, request) {
$rootScope.$apply(function () {
r.onTransportFailure(errorMsg, request);
});
};
}
else if (property === 'onReconnect') {
result.onReconnect = function (request, response) {
$rootScope.$apply(function () {
r.onReconnect(request, response);
});
};
}

Angular Directive Follow/Unfollow button

I'm trying to make angular directive button to follow and unfollow leagues ID
every request $http.put going fine but there is a problem with .then method console show me error and the method rejected
here the code
app.factory('FollowedLeagues', ['appConfig', '$http', '$q', function(appConfig, $http, $q){
var FollowedLeagues = {};
FollowedLeagues.follow = function (token, leagueID) {
$http.put(appConfig.apiUrl + 'user/follow-league?token=' + token +'&league_id='+ leagueID +'&status=true' )
.then(function(response){
if (typeof response.data === 'object') {
return response.data;
} else {
// invalid response
return $q.reject(response.data);
}
},
function(response) {
// something went wrong
return $q.reject(response.data);
});
};
FollowedLeagues.unfollow = function (token, leagueID) {
$http.put(appConfig.apiUrl + 'user/follow-league?token=' + token +'&league_id='+ leagueID +'&status=false' )
.then(function(response){
if (typeof response.data === 'object') {
return response.data;
} else {
// invalid response
return $q.reject(response.data);
}
},
function(response) {
// something went wrong
return $q.reject(response.data);
});
};
return FollowedLeagues;
}]);
app.directive('fbFollowBtn', ['$rootScope', '$compile', 'FollowedLeagues', function ($rootScope, $compile, FollowedLeagues) {
var getLeagueID = function(leagueID, followed){
for(var i=0; i< followed.length; i++) {
var fLeagues = followed[i]._id;
if (fLeagues == leagueID) {
return fLeagues;
}
}
};//End-function.
return {
restrict: 'A',
link:function(scope, element, attrs){
scope.followed = $rootScope.meData.followedLeagues;
scope.leagueid = attrs.leagueid;
var follow_btn = null;
var unfollow_btn = null;
var createFollowBtn = function () {
follow_btn = angular.element('Follow');
$compile(follow_btn)(scope);
element.append(follow_btn);
follow_btn.bind('click', function(e){
scope.submitting = true;
FollowedLeagues.follow($rootScope.userToKen, scope.leagueid)
.then(function(data){
scope.submitting = false;
follow_btn.remove();
createUnfollowBtn();
console.log('followed Leagues Done :-) ', data);
});
// scope.$apply();
});
};
var createUnfollowBtn = function () {
unfollow_btn = angular.element('Unfollow');
$compile(unfollow_btn)(scope);
element.append(unfollow_btn);
unfollow_btn.bind('click', function (e) {
scope.submitting = true;
FollowedLeagues.unfollow($rootScope.userToKen, scope.leagueid)
.then(function(data){
scope.submitting = false;
unfollow_btn.remove();
createFollowBtn();
console.log('followed Leagues Done :-) ', data);
});
// scope.$apply();
});
};
scope.$watch('leagueid', function (val) {
var leag = getLeagueID(scope.leagueid, scope.followed);
if(typeof(leag) == 'undefined'){
createFollowBtn();
} else if(typeof(leag) !== 'undefined'){
createUnfollowBtn();
}//end if
}, true);
}
};
}]);
You have to return your $http.put function inside your service functions. For example the Followedleagues.follow function:
FollowedLeagues.follow = function (token, leagueID) {
return $http.put(appConfig.apiUrl + 'user/follow-league?token=' + token +'&league_id='+ leagueID +'&status=true' )
.then(function(response){
if (typeof response.data === 'object') {
return response.data;
} else {
// invalid response
return $q.reject(response.data);
}
},
function(response) {
// something went wrong
return $q.reject(response.data);
});
};

Categories

Resources