this is more a Design question:
I have an angularJS app,
this app, uses a Service to communicate with an API which has a sign-in functionality...
app.service('managerApiService', function($q){
var myApi = new WWW_Wrapper(...);
myApi.setInput('www-asynchronous', true);
var defer = $q.defer();
this.login = function(){
...
};
this.logout = function(){
...
};
this.getShops = function(){
...
return defer.promise;
}
});
and another service, that handles the User Login/Credentials/Info:
app.service('loginService', function(){
this.credentials = {username: null, password: null };
this.loginData = null; // comes from server during login...
this.login = function(){
...
};
this.logout = function(){
...
};
});
My question is:
LoginService
inject managerApiService
, and update it's credentials? managerApiService
inject LoginService
and watch for it's credentials? Any other idea?
The way I do it is, usually having one service that is responsible for communicating with the API but does not care about state. All it cares about is creating requests and returning results. Then, I have another service that takes care of the session, and this service handles the state (username, password, etc...). This service (Session) is injected with the API service, and calls it's methods. The API, however, is never aware of the existence of this server.
In more detail, I usually have a service that is responsible for communicating with the backend (which is the analogous to your managerApiService, I assume). Like this:
app.service('managerApiService', [ '$q', function ( $q ) {
this.login = function ( credentials ) {
// ...
};
this.logout = function () {
// ...
};
} ] );
Note that this service does not store any information related to the login or session.
Then I use another service that is responsible for maintaining the session, which means it stores the current's user id, the user's information, permissions or whatever else is necessary. This service delegates the task of actually performing the login to the previous service, which could look something like this
app.service('loginService', [ 'managerApiService', function ( managerApiService ) {
this.loginData = null;
this.login = function ( credentials ) {
return managerApiService.login( credentials ).then( /* ... */ );
};
this.logout = function () {
...
};
} ] );
What is the main advantage: Since the communication with the server is abstracted, you can change how the server works and only have to update the API service. Or you can even add new login providers, and your application doesn't even need to know. The API will take care of making the appropriate request.
Basically, you are in the right path. The only difference I would make is not storing the credentials on the LoginService, and instead storing them on the view or controller. This is because the LoginService stays alive for the whole application, not only the login screen, and there's no need for the credentials to be stored in memory after the login has been performed.
As for errors, I make the server return an error code, like 400, or 401. Then on the controller, I usually listen for a .catch
to deal with the errors, usually setting up a temporary variable in the scope saying that the credentials are wrong.