Обещание не разрешено после сбоя проверки

У меня есть форма входа, которая создается через объект обещания. Все работает нормально, за исключением случая, когда в действие вступает проверка формы. Вот мой 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
   };
 });

Теперь, что происходит, когда я захожу в форму в первый раз и отправляю форму с действительными результатами, процесс входа в систему проходит успешно, и я перенаправляюсь на «подробности». Но если имя пользователя или пароль неверны и форма отклонена, появляется ошибка.

И затем, после этого, если я ввожу правильные учетные данные и нажимаю «Отправить», я не перенаправляюсь на «подробности» и не застреваю в той же форме входа, а эта ошибка все еще отображается «Вверх». Но когда я обновляю страницу, я уже вошел в систему. Это связано с тем, что был выполнен HTTP-запрос и установлена ​​информация о пользователе.

Я отладил код и обнаружил, что функция then не выполняется в моем $scope.submit, и это может быть связано с тем, что обещание не было разрешено. Я пробовал несколько scope.apply и другие вещи, но ничего не получалось. Может ли кто-нибудь помочь, что здесь происходит.


person ronit    schedule 17.02.2017    source источник


Ответы (2)


Как сказал @Akis, вы создаете отложенное только один раз, поэтому, как только оно будет выполнено (или отклонено) один раз, вот и все, навсегда для этого обещания. Это связано с тем, что обещание может быть «разрешено» только один раз (либо выполнено, либо отклонено).

P.S. любимая ненависть... язык обещаний - решенное обещание означает выполненное или отклоненное - но в большинстве примеров используется имя resolve для выполнения!!

Я добавил этот ответ, потому что вам вообще не нужно использовать deferred, поскольку $http явно возвращает обещание - использование deferred (или конструктора 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
    };
});
person Jaromanda X    schedule 17.02.2017

Это потому, что обещание уже выполнено.

Попробуйте переместить объявление 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
   };
person Sarantis Tofas    schedule 17.02.2017
comment
Спасибо @akis, это сработало. Честно говоря, я был в большом замешательстве по поводу концепции обещания. Но это многое прояснило. Не было необходимости в отрицательной оценке. Я новичок в Angular и переполнении стека. :( - person ronit; 18.02.2017
comment
@ronit, кстати, это не я проголосовал против: D, твой вопрос был в порядке - person Sarantis Tofas; 26.05.2017