为什么 $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 函数为什么以及何时使用它。问题解决了。
我正在为 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 函数为什么以及何时使用它。问题解决了。