AngularJS отложил определенное поведение внутри области видимости

Предположим, что у нас есть такой html-код:

<button
  id="my-login-button"
  ng-hide="loggedIn"
  ng-click="login()">Log me in!</button>

Также у нас есть JavaScript:

// controller.js
$scope.login = function () {
    API.login()
      .then(function () {
        console.log('login promise resolved');
      });
};

// service.js
app.factory('API', ['$q', '$timeout', function ($q, $timeout) {
  return {
    login: function () {
      var login = $q.defer();

      // async login
      VK.Auth.login(
        function () {
          // login.resolve();       // doesn't work without $timeout()
          $timeout(login.resolve);  // works as it should
        },
        VK.access.FRIENDS | VK.access.AUDIO
      );

      return login.promise;
    }
  };
}]);

Этот фрагмент кода работает правильно, но загадочная часть находится рядом с функцией $timeout(). Почему я должен оборачивать свое решение этим? Почему без него код не работает должным образом?

Я ничего не делаю с переменными области видимости, я просто утешаю. И без $timeout он будет вызываться со следующим дайджестом...

Как по мне это не имеет смысла, если мне нужно будет менять прицельные пропсы, я заверну все в $apply.

Кто-нибудь может объяснить, почему обычное отложенное поведение стало таинственным?

P.S. Я решил свою проблему с $timeout после прочтения ответов на этот вопрос.


person ValeriiVasin    schedule 29.05.2013    source источник


Ответы (1)


В AngularJS результаты промисов распространяются асинхронно, внутри цикла $digest. Таким образом, результаты then() не распространяются до следующего цикла дайджеста, который никогда не приходит без $timeout, $http или $apply для его запуска.

См. также Обратный вызов Promise не вызывается в Angular JS

person Mark Rajcok    schedule 29.05.2013
comment
Я полагаю, что только $q ведет себя так. Если мы попытаемся вместо этого использовать $.Deferred() - он не будет ждать следующего цикла дайджеста... И это странно... - person ValeriiVasin; 30.05.2013