AngularJS控制器为:承诺不更新视图

时间:2018-09-28 21:41:00

标签: angularjs typescript

我曾用头撞墙,试图弄清楚controller as和Promises如何与AngularJS一起工作。通过将结果包装在Promise中,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.log(this, self, this.self);
        this.lastAuthSuccessful = success;
      })

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

以及auth服务中的指纹方法:

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拒绝更新视图,直到您尝试再次调用该方法为止。

2 个答案:

答案 0 :(得分:0)

angular.js著名(或臭名昭著)使用the digest loop进行更改检测。像ng-click这样的内置角度指令会为您调用$scope.$digest(),但是在您的更改是在诺言解决后异步进行的,没有人调用$digest()

因此,您可以在promise的$scope.$digest()块中自己调用then,也可以使用$q(它是Promises的angular的实现),它调用{{ 1}}。

答案 1 :(得分:0)

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;
}