验证失败后,承诺未解决

时间:2017-02-17 18:24:02

标签: javascript angularjs promise angular-promise deferred

我有一个通过promise对象创建的登录表单。 一切正常,除了形式验证开始实施的情况。 这是我的html文件。

   <form id="signin" class="signinform" autocomplete="off"> 
   <span ng-show="errorName" class="error_block">{{ errorName }}</span>
   <input placeholder="User Name" ng-model="user.name" type="text" name="user_name" required>
   <input placeholder="Password" ng-model="user.password" type="password" name="password" required>
  <input type="submit" ng-click="submit(user)" value="Log IN" id="submit">
</form>

这是写入ng-click的控制器

  $scope.submit =  function(user){
   LoginService.login(user)
    .then(function(response) {           
         var userInfo = response.userName
         $rootScope.$emit('myEvent',userInfo);
         $location.path("/details/1");
    },
    function(error) {
      $scope.errorName = "Invalid Username or Password";
    });
 }

这是

的工厂服务
app.factory("LoginService", function($http, $q, $window) {
var userInfo;
var deferred = $q.defer();
 function login(user) {
  $http({
   method: 'POST',
   url: "login.php",
   data: { "userName": user.name, "password": user.password },
   headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
   }).then(function(result) { 
   userInfo = {
    accessToken: result.data.login.token,
    userName: result.data.login.name
   };
   $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);  
    deferred.resolve(userInfo);
    }, function(error) {
    deferred.reject(error);
   });      
   return deferred.promise;
   }

   return {
    login: login
   };
 });

现在发生的情况是,当我第一次访问表单并提交有效结果的表单时,登录过程成功,我被重定向到'详细信息'。但是如果用户名或密码出错并且表单被拒绝则错误出现了。

然后,如果我输入正确的凭据并点击提交,我不会被重定向到'详细信息'并停留在同一登录表单上,但该错误仍然显示为Up。 但是当我刷新页面时,我已经登录了。那是因为http请求已经发生并且已经设置了userInfo。

我调试了代码并发现then函数没有在我的$ scope.submit中执行,这可能是因为promise没有得到解决。我曾尝试过几个scope.apply和其他东西,但没有任何效果。 任何人都可以帮助解决这里发生的事情。

2 个答案:

答案 0 :(得分:2)

正如@Akis所说,你只创造了一次延期,所以一旦它完成(或拒绝)一次,那就是它,永远是为了这个承诺。这是因为承诺可以被解决&#34;只有一次(完成或拒绝)

  

P.S。宠物仇恨......承诺的语言 - 已解决的承诺意味着满足或拒绝 - 但大多数例子使用名称resolve来实现!!

我已添加此答案,因为您根本不需要使用延迟,因为$ http明确返回一个承诺 - 在此实例中使用延迟(或new Promise构造函数)被视为反模式

另请注意,我在执行$window.sessionStorage.removeItem("userInfo");之前添加了$http - 此时清除sessionInfo似乎合乎逻辑

app.factory("LoginService", function($http, $q, $window) {
    function login(user) {
        // added this as it seems it should be done!
        $window.sessionStorage.removeItem("userInfo");
        return $http({
            method: 'POST',
            url: "login.php",
            data: {
                "userName": user.name,
                "password": user.password
            },
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
            }
        }).then(function(result) {
            var userInfo = {
                accessToken: result.data.login.token,
                userName: result.data.login.name
            };
            $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
            return userInfo;
        });
    }
    return {
        login: login
    };
});

答案 1 :(得分:0)

这是因为承诺已经解决了。

尝试在var deferred = $q.defer();函数中移动login声明。

function login(user) {
  var deferred = $q.defer();

  $http({
   method: 'POST',
   url: "login.php",
   data: { "userName": user.name, "password": user.password },
   headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'}
   }).then(function(result) { 
   userInfo = {
    accessToken: result.data.login.token,
    userName: result.data.login.name
   };
   $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);  
    deferred.resolve(userInfo);
    }, function(error) {
    deferred.reject(error);
   });      
   return deferred.promise;
   }

   return {
    login: login
   };