2017-02-17 78 views
1

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

<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-点击写入

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

现在工厂服务发生的事情是,当我访问的形式第一时间和提交有效结果的登录过程是成功的,我被重定向到“details”。但如果用户名或密码出错,表单被拒绝,错误就会显示出来。

再之后,如果我输入正确的凭据并点击提交我没有重定向到“细节”,并坚持这个错误仍然显示相同的登录表单上。 但是,当我刷新页面,我已经登录。那是因为http请求已发生并且userInfo已设置。

我调试的代码,发现当时的功能没有被我的$ scope.submit执行,并且可能是因为承诺一直没有得到解决。我曾尝试过几个scope.apply和其他东西,但没有任何工作。 任何人都可以帮助这里发生的事情。

回答

2

正如@Akis说,你创建一个延期一次,所以一旦它的达成(或拒绝)一次,就是这样,永远在这个承诺。这是因为承诺只能“解决”一次(要么完成或拒绝)

P.S.宠物讨厌...承诺的语言 - 解决的承诺意味着实现或拒绝 - 但大多数例子使用名称resolve履行!

我已经添加了这个答案,因为你并不需要使用所有推迟做,看到$ HTTP明确返回一个承诺 - 在这种情况下使用延迟(或new Promise构造函数)被认为是一种反模式

还要注意,我说是执行$http之前$window.sessionStorage.removeItem("userInfo"); - 似乎是合乎逻辑清除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 
    }; 
}); 
+0

是的,这就是似乎顺理成章,感谢名单.. – ronit

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 
    }; 
+0

感谢名单@akis,即工作。老实说,我对这个承诺概念感到困惑。但是这清除了很多。没有必要负score.i的是新的角度和堆栈溢出:( – ronit

+0

@ronit BTW它不是我downvoted:d您的问题就好了 – Akis