when to use $q.defer() in Angularjs

30,330

Solution 1

Simply put you can use $q.defer() to create a Promise. A Promise is a function that returns a single value or error in the future. So whenever you have some asynchronous process that should return a value or an error, you can use $q.defer() to create a new Promise.

In most cases though, Angular has already done this for you and you can simply use the Promise that is returned, for instance by the $http service. Your example shows a good example of when you'd want to create your own.

You see, normally the $http service returns the value from the server, or an error when the http call fails. In your example however you also want to return an error from the Promise (= reject it) when the http call itself success, but has a not-true value for the success property.

To do this, the example creates a new Promise whose return value (or error) can then be manually controlled. In this example by calling the resolve() (= return the value) function only when the http call is successful and has data.success == true. In all other cases (when the http call fails or doesn't have the correct data.status value) the newly created Promise is rejected (= return error).

Solution 2

$q.defer() allows you to create a promise object which you might want to return to the function that called your login function.

Make sure you return deferred.promise rather than the entire deferred object so that only the function that created your deferred object can call resolve() or reject() on it, but the calling function of login can still wait for the promise to be fulfilled. Make sense?

Share:
30,330
juliana Morales
Author by

juliana Morales

Updated on December 13, 2020

Comments

  • juliana Morales
    juliana Morales over 3 years

    I am new to Angularjs and I m following this tutorial :http://mherman.org/blog/2015/07/02/handling-user-authentication-with-the-mean-stack/#.WE70iubhCM8 . However i dont understand when to use $q.defer(). For example in the folllowing Angularjs code why use $q.defer() :

    function login(username, password) {
    
          // create a new instance of deferred
          var deferred = $q.defer();
    
          // send a post request to the server
          $http.post('/user/login',
            {username: username, password: password})
            // handle success
            .success(function (data, status) {
              if(status === 200 && data.status){
                user = true;
                deferred.resolve();
              } else {
                user = false;
                deferred.reject();
              }
            })
            // handle error
            .error(function (data) {
              user = false;
              deferred.reject();
            });
    

    The server side code is :

    router.post('/login', function(req, res, next) {
      passport.authenticate('local', function(err, user, info) {
        if (err) {
          return next(err);
        }
        if (!user) {
          return res.status(401).json({
            err: info
          });
        }
        req.logIn(user, function(err) {
          if (err) {
            return res.status(500).json({
              err: 'Could not log in user'
            });
          }
          res.status(200).json({
            status: 'Login successful!'
          });
        });
      })(req, res, next);
    });
    

    And why not use it in the following Angularjs code :

     function getUserStatus() {
          return $http.get('/user/status')
          // handle success
          .success(function (data) {
            if(data.status){
              user = true;
            } else {
              user = false;
            }
          })
          // handle error
          .error(function (data) {
            user = false;
          });
        }
    

    Server side code is :

    router.get('/status', function(req, res) {
      if (!req.isAuthenticated()) {
        return res.status(200).json({
          status: false
        });
      }
      res.status(200).json({
        status: true
      });
    });
    
  • Uzumaki Naruto
    Uzumaki Naruto over 6 years
    nicely explained. This is exactly what it does