シンプルな HTML5 ユーザー登録フォームがあります。input
に追加されたカスタム関数を使用して、同じユーザー名を持つユーザーが存在しないことを確認するために、ユーザー名の値が検証され$asyncValidators
ます。
次の状況を考慮してください。
- ユーザーがユーザー名 (「Me」など) の入力を開始します。
- 少し遅れて、Angular バリデーターが実行され、ユーザー名が使用可能かどうかを尋ねる非同期要求がサーバーに送信されます。
- ユーザーはさらに文字を入力し始めます (たとえば、'Me123')。
- 少し遅れて、Angular はサーバーに別のリクエストを送信して、ユーザー名の検証を再度試みます。
ユーザー名の有効性に関して 2 つの応答を受け取った場合、Angular は何をしますか? これを優雅に処理する方法はありますか?
私がやりたいことは、ユーザーがユーザー名の値を変更するとすぐに、最初の検証試行の結果をキャンセルするか、Angular に無視するように指示することです。
編集 11/12/2015:
シロッコの答えは、私の質問を明確にするのに役立ちました。ここには 2 つの部分があります。
- 実際の HTTP リクエストを中止する
- Angular 検証プロセスに、返された promise
$asyncValidators.usernameAvailable
が解決または拒否されるのを待つのをやめるように指示します。
timeout
サービスのオプションを使用して、最初のことができました$http
。私の質問は次のとおりです。2番目のことを行う必要があるか、望ましいか、または可能ですか? もしそうなら、どのように?
keyup
これは、ディレクティブの要素に追加されたイベント ハンドラーで発生する可能性があると考えていlink
ます。下記参照:
index.html
<input
ng-model="user.username"
ng-model-options="{ debounce: 250 }"
check-availability />
checkAvailability.directive.js
function affectsText(keyCode) {
// some code to determine if keyCode could change value of a text input
}
angular
.module('app')
.directive('checkAvailability', ['$q', 'users', function($q, users) {
return {
restrict: 'AC',
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
element.on('keyup', function(e) {
if (!affectsText(e.keyCode)) {
return;
}
// cancel previous $asyncValidators.usernameAvailable process??
// users service cancels operation by rejecting a promise previously assigned to to $http's timeout option
users.cancelIsAvailableCheck();
});
ctrl.$asyncValidators.usernameAvailable = function(modelValue) {
if (ctrl.$isEmpty(modelValue)) {
return $q.when();
}
var deferred = $q.defer();
users.isAvailable(modelValue).then(function(available) {
if (available) {
deferred.resolve();
} else {
deferred.reject();
}
});
return deferred.promise;
}
}
};
}]);