2017-02-17 80 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