CodeMed
CodeMed

Reputation: 9201

How does callback work in AngularJS call to REST service?

I am studying AngularJS and REST. A code sample uses the word callback repeatedly in an authentication function. Is "callback" a keyword in JavaScript or Angular? Or is callback just a custom variable created in this code?

How does callback work in the code below? Googling callback and AngularJS is not producing usable results. The code for the AngularJS module in question can be read at this link, which also contains all the code for the sample app.

Here is the module code itself:

angular.module('auth', []).factory( 'auth',

    function($rootScope, $http, $location) {

        enter = function() {
            if ($location.path() != auth.loginPath) {
                auth.path = $location.path();
                if (!auth.authenticated) {
                    $location.path(auth.loginPath);
                }
            }                   
        }

        var auth = {

            authenticated : false,

            loginPath : '/login',
            logoutPath : '/logout',
            homePath : '/',
            path : $location.path(),

            authenticate : function(credentials, callback) {

                var headers = credentials && credentials.username ? {
                    authorization : "Basic "
                            + btoa(credentials.username + ":"
                                    + credentials.password)
                } : {};

                $http.get('user', {
                    headers : headers
                }).success(function(data) {
                    if (data.name) {
                        auth.authenticated = true;
                    } else {
                        auth.authenticated = false;
                    }
                    callback && callback(auth.authenticated);
                    $location.path(auth.path==auth.loginPath ? auth.homePath : auth.path);
                }).error(function() {
                    auth.authenticated = false;
                    callback && callback(false);
                });

            },

            clear : function() {
                $location.path(auth.loginPath);
                auth.authenticated = false;
                $http.post(auth.logoutPath, {}).success(function() {
                    console.log("Logout succeeded");
                }).error(function(data) {
                    console.log("Logout failed");
                });
            },

            init : function(homePath, loginPath, logoutPath) {

                auth.homePath = homePath;
                auth.loginPath = loginPath;
                auth.logoutPath = logoutPath;

                auth.authenticate({}, function(authenticated) {
                    if (authenticated) {
                        $location.path(auth.path);
                    }
                })

                // Guard route changes and switch to login page if unauthenticated
                $rootScope.$on('$routeChangeStart', function() {
                    enter();
                });

            }

        };

        return auth;

    });

Additional information

Based on @okonyk's response, I am including code from a different module that calls the auth.authenticate() function:

$scope.login = function() {
    auth.authenticate($scope.credentials, function(authenticated) {
        if (authenticated) {
            //do some stuff
             $scope.error = false;
         } else { 
            $scope.error = true;
        }
    })
}

So how does the call from login() to auth.authenticate($scope.credentials, function(authenticated) work? Is the function(authenticated) parameter sending a boolean that determines functionality inside auth.authenticate()? For example true might indicate to do the callback, while false might indicate note to do the callback, but it would help to have it explained.

You can read the code in the sample app for the other module with the login() method by clicking on this link.

Upvotes: 10

Views: 26428

Answers (2)

Mr. Baudin
Mr. Baudin

Reputation: 2254

Basically writing something like

callback && callback(auth.authenticated);

or

callback && callback(false);

means that if that callback exists and then calls it.

simple example:

function foo () {
   console.log('foo');
   return 'Fighting foo!';
}

foo && foo();

It is just a language construct, a weird one and not a great practice for readability. This code also implies that the result of calling foo() should be valid but this is never handled. I'd use a simple if statement.

Upvotes: 0

oKonyk
oKonyk

Reputation: 1476

Here is pretty good explanation:

A callback function, also known as a higher-order function, is a function that is passed to another function (let’s call this other function “otherFunction”) as a parameter, and the callback function is called (or executed) inside the otherFunction. A callback function is essentially a pattern (an established solution to a common problem), and therefore, the use of a callback function is also known as a callback pattern.

callback is not a keyword, its just a name of parameter that is passed into the function, you can call it whatever you want (callback or cb is pretty common).

I'll try to explain it on example of super simplistic custom build callback function:

function useAsCallback(string){
  console.log("callback is being executed with passed parameter: " + string)
}

function main(param, callback){
  callback(param)
}

main(123456, useAsCallback)

if you run this, it would print: callback is being executed with passed parameter: 123456

Callback pattern is commonly used to handle JavaScript asynchronous behavior.

EDIT: more specific example:

Talking about your code snippet... lets say you'll inject your factory into controller.

Now you have auth.authenticate method exposed. You have to pass two parameters(credentials, callback).

auth.authenticate({username: Joe, password: 123456}, function(authStatus){
  if(authStatus){
    console.log("Successfully authenticated")
  }else{
    console.log("Access denied")
  }
});

We just passed anonymous function as a callback parameter of our auth.authenticate method.

EDIT: responce to 'ADDITIONAL INFORMATION':

It looks like there might be some misunderstanding. You are asking:

Is the function(authenticated) parameter sending a boolean that determines functionality inside auth.authenticate()

Thing is that, it is complete opposite: auth.authenticate() passes value into 'function(authenticated)', which is anonymous function. It happens at this point: callback && callback(auth.authenticated); - on .success or callback && callback(false); - on .error

Upvotes: 9

Related Questions