hug*_*ige 22 javascript asynchronous angularjs
我知道有几种方法可以在角度js中加载指标(例如:https://gist.github.com/maikeldaloo/5140733).
但是它们要么必须为每一个呼叫配置,要么 - 如果它们按照我的意愿全局行动 - 只应用于http请求,而不是应用于服务中使用的$ q-promises.
到目前为止,我见过的全球负荷指标都适用
$httpProvider.responseInterceptors.push(interceptor);
Run Code Online (Sandbox Code Playgroud)
是否有类似的东西$q
,比如$qProvider.reponseInterceptors
?如果没有,那么实现这种功能最方便的方法是什么?例如,是否可以使用某种类型的装饰器图案?
Kos*_*rov 16
虽然我发现它非常复杂,不必要且可能已损坏,但您可以 装饰$q
并覆盖其defer
功能.
每当有人要求新的时,defer()
它就会运行你自己的版本,这也增加了一个计数器.在分发defer
对象之前,您注册一个finally
回调(仅限Angular 1.2.0,但always
也可能适合)以减少计数器.
最后,添加一个$rootScope
监视器来监视此计数器何时大于0(比pendingPromisses
进入$rootScope
和绑定更快ng-show="pendingPromisses > 0"
).
app.config(function($provide) {
$provide.decorator('$q', ['$delegate', '$rootScope', function($delegate, $rootScope) {
var pendingPromisses = 0;
$rootScope.$watch(
function() { return pendingPromisses > 0; },
function(loading) { $rootScope.loading = loading; }
);
var $q = $delegate;
var origDefer = $q.defer;
$q.defer = function() {
var defer = origDefer();
pendingPromisses++;
defer.promise.finally(function() {
pendingPromisses--;
});
return defer;
};
return $q;
}]);
});
Run Code Online (Sandbox Code Playgroud)
然后,绑定到继承自的范围的视图$rootScope
可以具有:
<span ng-show="loading">Loading, please wait</span>
Run Code Online (Sandbox Code Playgroud)
(这在带有隔离范围的指令中不起作用)
在这里看到它.
在为当前稳定1.2.0工作的官方文档中有一个很好的例子.
http://docs.angularjs.org/api/ng.$http(页面的前四分之一,搜索拦截器)
我对这些文档的提取引出了我的解决方案:
angular.module('RequestInterceptor', [])
.config(function ($httpProvider) {
$httpProvider.interceptors.push('requestInterceptor');
})
.factory('requestInterceptor', function ($q, $rootScope) {
$rootScope.pendingRequests = 0;
return {
'request': function (config) {
$rootScope.pendingRequests++;
return config || $q.when(config);
},
'requestError': function(rejection) {
$rootScope.pendingRequests--;
return $q.reject(rejection);
},
'response': function(response) {
$rootScope.pendingRequests--;
return response || $q.when(response);
},
'responseError': function(rejection) {
$rootScope.pendingRequests--;
return $q.reject(rejection);
}
}
});
Run Code Online (Sandbox Code Playgroud)
然后,您可以在ng-show表达式中使用pendingRequests> 0.
自OP请求以来,这是基于我们正在使用的应用程序的方法.此方法不会不改变的行为$q
,而增加了一个非常简单的 API来处理需要某种形式的视觉指示的承诺.虽然这需要在每个使用的地方进行修改,但它只是一个单行.
比方说ajaxIndicator
,有一项服务知道如何更新UI的一部分.每当类似承诺的对象需要提供指示,直到承诺得到解决,我们使用:
// $http example:
var promise = $http.get(...);
ajaxIndicator.indicate(promise); // <--- this line needs to be added
Run Code Online (Sandbox Code Playgroud)
如果您不想保留对承诺的引用:
// $http example without keeping the reference:
ajaxIndicator.indicate($http.get(...));
Run Code Online (Sandbox Code Playgroud)
或者使用资源:
var rc = $resource(...);
...
$scope.obj = rc.get(...);
ajaxIndicator.indicate($scope.obj);
Run Code Online (Sandbox Code Playgroud)
(注意:对于Angular 1.2,这需要tweeking,因为$then()
资源对象上没有.)
现在在根模板中,您必须将指标绑定到$rootScope.ajaxActive
,例如:
<div class="ajax-indicator" ng-show="ajaxActive"></div>
Run Code Online (Sandbox Code Playgroud)
(从我们的源代码修改.)警告:此实现不考虑嵌套调用!(我们的要求是UI阻塞,所以我们不希望嵌套调用;如果感兴趣,我可以尝试增强此代码.)
app.service("ajaxIndicator", ["$rootScope"], function($rootScope) {
"use strict";
$rootScope.ajaxActive = false;
function indicate(promise) {
if( !$rootScope.ajaxActive ) {
$rootScope.ajaxActive = true;
$rootScope.$broadcast("ajax.active"); // OPTIONAL
if( typeof(promise) === "object" && promise !== null ) {
if( typeof(promise.always) === "function" ) promise.always(finished);
else if( typeof(promise.then) === "function" ) promise.then(finished,finished);
else if( typeof(promise.$then) === "function" ) promise.$then(finished,finished);
}
}
}
function finished() {
$rootScope.ajaxActive = false;
}
return {
indicate: indicate,
finished: finished
};
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14554 次 |
最近记录: |