AngularJS Controller As: обещание не обновлять представление

Бился головой о стену, пытаясь понять, как controller as и Promises работают вместе с AngularJS. Кажется, что, заключив результат в обещание, AngularJS не видит обновления контроллера, пока вы не активируете другое изменение.

HTML:

<body ng-app = "MainModule" ng-controller = "MainController as main">
    <div class = "bar bar-header bar-calm">
        <h1 class = "title">Test Bench</h1>
    </div>

    <div class = "app">
        <h1>Test Bench</h1>

        <div class = "text-center">
            <p>Last Fingerprint Result: {{main.lastAuthSuccessful}}</p>
        </div>
.....
</body>

Рассматриваемый метод контроллера:

doFingerprint() {
    this.auth
      .fingerprint()

      .then(success => {
        console.info(this, self, this.self);
        this.lastAuthSuccessful = success;
      })

      .catch(error => {
        console.error(error);
        return false;
      });
  }

И метод отпечатка пальца в сервисе аутентификации:

fingerprint(): Promise<boolean> {
    if (!this.finger) return Promise.reject("Fingerprint API not yet loaded.");

    return new Promise((resolve, reject) => {
      this.finger.show(
        {
          clientId: "Fingerprint-Demo",
          clientSecret: "password"
        },

        () => {
          resolve(true);
        },

        err => {
          resolve(false);
        }
      );
    });
  }

Это кажется довольно простым, но обновленный lastAuthSuccessful из обещания отказывается обновлять представление, пока вы не попытаетесь снова вызвать метод.

Знаете ли вы, что директивы являются одной из самых мощных и универсальных функций Angular?
Знаете ли вы, что директивы являются одной из самых мощных и универсальных функций Angular?
Директивы позволяют расширять HTML новыми элементами и атрибутами и даже создавать собственные структурные директивы для манипулирования DOM. С...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
1
0
787
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как известно, angular.js (или, скорее, печально) использует цикл дайджеста для обнаружения изменений. Встроенные директивы angular, такие как ng-click, будут вызывать $scope.$digest() за вас, но здесь ваше изменение выполняется асинхронно, когда обещание выполняется, и никто не вызывает $digest().

Итак, вы можете либо вызвать $scope.$digest() самостоятельно в блоке then обещания, либо использовать $ q, который является реализацией обещаний angular, где он вызывает $digest за вас.

Ответ принят как подходящий

В Angular есть собственная реализация Promise - $ q. ES6 Promise не запускает цикл дайджеста Angular, вместо этого вы должны использовать $ q.

Если вы настаиваете на использовании ES6 Promise, вы можете вызвать $ scope. $ Apply (). $ apply () используется для выполнения выражения в AngularJS вне фреймворка AngularJS. (Например, из событий DOM браузера, setTimeout, XHR или сторонних библиотек).

Обычно не вызывает $ digest () непосредственно в контроллерах или в директивах. Вместо этого вы должны вызвать $ apply () (обычно из директивы), что вызовет $ digest ().

fingerprint(): Promise<boolean> {
    let deferred = $q.defer();
    if (!this.finger) return $q.reject("Fingerprint API not yet loaded.");

    this.finger.show(
        {
          clientId: "Fingerprint-Demo",
          clientSecret: "password"
        },

        () => {
          deferred.resolve(true);
        },

        err => {
          deferred.resolve(false);
        }
      );

    return deferred.promise;
}

Другие вопросы по теме