为什么 $q 需要一段时间才能解决

Why would $q take a while to resolve

我正在为 Umbraco 编写 AngularJS 插件,并创建了一个简单的视图、控制器和服务。但出于某种原因,我的承诺需要一段时间才能兑现。

我已经使用内置的 $q 服务来创建 return 我的承诺,我已经注销了我的变量,并且可以看到异步服务何时完成,但是这与解析之间存在明显的时间差异正在调用函数。

从那以后,我发现承诺看起来像是在等待 Umbracos GetRemainingTimeout 服务才能解决。

有人可以解释为什么会这样吗?

viewController.js

angular.module('umbraco')
  .controller('JaywingAnalyticsHelper.ViewController', function ($scope, googleService) {
    googleService.checkAuth().then(function (signedIn){
      $scope.isAuthorised = signedIn;
      console.log(signedIn);
    });
  });

googleService.js

angular.module("umbraco")
  .service('googleService', function ($q) {

    var clientId = 'REMOVED_FOR_PRIVACY',
      scopes = ['https://www.googleapis.com/auth/analytics.readonly'],
      deferred = $q.defer();

    this.checkAuth = function () {
      gapi.load('auth2', function () {
        gapi.auth2.init().then(function () {
          var googleAuth = gapi.auth2.getAuthInstance();
          var signedIn = googleAuth.isSignedIn.get();
          console.log(signedIn);
          deferred.resolve(signedIn);
        }, function(){
          deferred.reject(false);
        });
      });

      return deferred.promise;
    };
  });

Umbraco 版本 - 7.5.12
Angular 版本 - 1.1.5

找时间重新审视这个问题后,我发现了为什么 promise 花了这么长时间才回应的原因。

大多数端点可以在 angular 内通过使用 $http 服务到达,但 gapi 使用自己的方法发出请求并且由于 angular 生命周期 重要的是调用 $apply 提示 angular 更新任何绑定或观察者。

这里有两个指向文档和另一个重要资源的链接: https://code.angularjs.org/1.1.5/docs/api/ng.$rootScope.Scope#$apply http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

这简单得令人讨厌,只能归咎于我缺乏 angular 知识。在我的例子中,承诺等待 angular 到达其生命周期中的某个点,然后再解决承诺而不是立即更新。将其包装在 apply 函数中可以解决此问题。

$rootScope.$apply(function(){
  deferred.resolve(signedIn);
});

对于那些感兴趣的人,我通过许多步骤诊断了这个问题,包括:

  • 将 gapi 调用移出服务并移回控制器

    这没有任何效果,promise 仍然需要一段时间才能解决。

  • 将 gapi 调用换成 setTimeout

    同样这没有任何效果,并且 promise 仍然需要一段时间才能解决,但确实表明该问题与 gapi 没有直接关系。

  • 添加多个不同长度的setTimeouts

    这是下一步,因为它证明了 promise 正在同时解决,即使它们应该相隔几秒钟。由此产生了两个重要的发现。与视图交互导致承诺解决(某种生命周期触发器)并且有一个名为 $timeout

  • 的 angular 版本的 setTimeout
  • 了解 $timeout 存在的原因

    这让我进一步了解了 angular 生命周期以及 $apply 函数为什么以及何时使用它。问题解决了。