我有一个通过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和其他东西,但没有任何效果。 任何人都可以帮助解决这里发生的事情。
答案 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
};