AngularJS - 如果有新请求,则取消之前的$ resource $ promises

时间:2014-07-24 22:01:51

标签: angularjs angular-resource angular-promise

我有一个包含2个字段的表单:用户名和密码 当我的用户名模型发生更改时,我会向API发出请求以执行某些检查。

当我将x个调用分隔t毫秒到$resource工厂时,我想知道是否:

  • 在我的控制器中,收到的最后一个$promise将对应于用户最后输入的内容。
  • 之前的承诺将被取消。

我试图找到一种模拟API调用延迟的方法(因为我在本地工作并且每个响应都是立即的)但我可以找到$http服务的示例。

这是一个揭露这种情况的jsFiddle:
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>

应用

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);

            });
        }
    }]);

谢谢!

1 个答案:

答案 0 :(得分: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
    };    
}]);

粗略如何取消之前的请求。

但请注意,即使您在建立连接时取消请求,它也将由服务器执行,在这种情况下,服务器将使用无用的请求充斥服务器。这不是一个好习惯。

在你的情况下,使用$ timeout和0.5秒的延迟可能会减少对服务器的不必要的调用。非常大概是这样的:

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);

    }
}]);