2

I have a form with 2 fields: username and password.
When my username model changes, I make a request to an API to perform some checks.

When I make x calls separated by t milliseconds to a $resource factory, I would like to know if :

  • in my controller, the last $promise received will correspond to the last input made by the user.
  • previous promises will be cancelled.

I tried to find out a way to simulate a delay on my API call (because I am working locally and each response is immediate) but I could just find examples for $http service.

Here is a jsFiddle to expose this case:
http://jsfiddle.net/Jfwh9/1/

HTML

<div ng-app="myApp">
    <form ng-controller="loginCtrl">
        Username: {{ username }}
        <br>Password: {{ password }}
        <br>
        <input name="username" placeholder="enter your username" type="text" 
            ng-model="username" ng-change="checkUsername()">

        <input name="password" placeholder="enter your password" type="password" 
            ng-model="password">
    </form>
</div>

App

var myApp = angular.module('myApp', ['ngResource']);

/*
 * PRE-LOGIN
 *
 */
myApp.factory( 'preLogin', ['$resource',
    function( $resource, constants ) {
        // Check if a username exists     
        return $resource( '/api/prelogin', {},
                      {
                          post: {
                              method : 'POST'
                          }
                      });
    }]);


/*
 * Login Controller
 *
 *
 */
myApp.controller('loginCtrl', ['$scope', 'preLogin',
    function( $scope, preLogin ) {
        $scope.username = '';
        $scope.password = '';

        // Do some check on the username...
        $scope.checkUsername = function() {
            console.log('prelogin... ', $scope.username);

            preLogin.post({
                username: $scope.username
            }).$promise.then( function( data ) { // Success
                console.log(data);

            }, function( error ) { // Error
                console.log(error);

            });
        }
    }]);

Thanks!

Niflhel
  • 663
  • 1
  • 5
  • 19

1 Answers1

0

http://jsfiddle.net/5B2U7/1/

myApp.factory( 'preLogin', ['$resource','$q',
function( $resource, $q ) {
    var canceler = $q.defer();

    var cancel = function() {
        canceler.resolve();
        canceler = $q.defer();
    };

    // Check if a username exists     
    // create a resource
    // (we have to re-craete it every time because this is the only
    // way to renew the promise)    
    var initRes = function() {
    cancel();    
    return $resource( '/api/prelogin', {},
                  {
                      post: {
                          method : 'POST',
                          timeout : canceler.promise
                      }
                  });
    };

    return {
        initRes: initRes,
        cancelRes: cancel
    };    
}]);

this is roughly how you would cancel previous requests.

However have in mind that even though you cancel the request if the connection is established it will be executed by the server, which in this case will flood the server with useless requests. And that is not a good practice.

In your case perhaps using $timeout with 0.5 sec of delay would reduce the unnecessary calls to the server. Very roughly something like this:

http://jsfiddle.net/G6uNU/1/

myApp.controller('loginCtrl', ['$scope', 'preLogin','$timeout',
function( $scope, preLogin,$timeout ) {
    var timer = false;
    $scope.username = '';
    $scope.password = '';

    // Do some check on the username...
    $scope.checkUsername = function() {
        console.log('prelogin... ', $scope.username);
        if (timer) {
            $timeout.cancel(timer);
        }
        timer = $timeout(function() {
                preLogin.initRes().post({
                username: $scope.username
            }).$promise.then( function( data ) { // Success
                console.log(data);

            }, function( error ) { // Error
                console.log(error);

            });
        }, 500);

    }
}]);
Tsonev
  • 435
  • 7
  • 17