咨询Angular中$rootScope.$emit('dispatchQuery')及$http回调内的使用
嘿,我来帮你把这个问题掰扯清楚!首先咱们先拆解$rootScope.$emit('dispatchQuery')的作用,再结合你给的代码聊聊它在$http回调里的使用场景。
先搞懂
$rootScope.$emit('dispatchQuery')到底是干嘛的 你已经熟悉普通JS回调了,那咱们对比着来理解:
- 普通JS回调是一对一绑定:你调用函数时传入的那个回调,是唯一会被触发的逻辑,耦合性比较强。
- 而AngularJS里的
$rootScope.$emit()是事件广播机制,属于一对多通知:它会在Angular的作用域体系里广播一个名为dispatchQuery的事件,任何提前用$rootScope.$on('dispatchQuery', function() { ... })注册了监听器的代码,都会收到这个通知并执行自己的逻辑。 - 另外要注意:
$emit是向上传播事件,但$rootScope已经是Angular作用域的最顶层了,所以这里的$emit其实就是给所有绑定在$rootScope上的dispatchQuery监听器发通知。
结合你的代码,看在$http回调里用它的场景
先帮你修正一下代码里的小错误(比如漏了$http依赖、对象语法错误),再加入$emit的场景:
(function() { angular.module('sp').factory('Object', [ '$rootScope', '$http', function($rootScope, $http) { var Object; return Object = { load: function(callback) { return $http({ method: "get", url: "http://myhost/bananas", options: {} }).success(function(response) { $rootScope.myItems = response.items; // 在这里添加事件广播 $rootScope.$emit('dispatchQuery'); return callback && callback(); }); } }; } ]); }).call(this);
为什么要在这里加$emit?举个实际的例子:
假设你的应用里有好几个独立组件——比如商品列表组件、统计面板组件、筛选器组件,它们都需要知道“数据加载完成”这件事,然后各自执行逻辑:
- 列表组件要刷新视图
- 统计面板要重新计算数据
- 筛选器要重置选项
如果用普通回调,你要么得给load方法传入一堆回调,要么把所有逻辑塞到一个回调里,代码会变得乱糟糟,耦合度极高。但用$emit的话,每个组件只需要自己注册监听器就行:
// 列表控制器里 angular.module('sp').controller('ItemListCtrl', ['$rootScope', '$scope', function($rootScope, $scope) { // 注册事件监听器 var unbind = $rootScope.$on('dispatchQuery', function() { console.log('数据加载完成,列表开始刷新视图'); // 这里写列表刷新的逻辑 }); // 记得在控制器销毁时解绑,避免内存泄漏 $scope.$on('$destroy', unbind); }]); // 统计控制器里 angular.module('sp').controller('StatsCtrl', ['$rootScope', '$scope', function($rootScope, $scope) { var unbind = $rootScope.$on('dispatchQuery', function() { console.log('数据加载完成,统计面板重新计算'); // 这里写统计计算的逻辑 }); $scope.$on('$destroy', unbind); }]);
这样一来,load方法只需要专注于加载数据,然后广播事件就行,完全不用关心哪些组件要响应,代码解耦得非常干净。
补充两个小细节
- 如果你想让事件从顶层向下传播到所有子作用域,可以用
$rootScope.$broadcast('dispatchQuery'),它和$emit的传播方向相反。 - 一定要记得解绑监听器:像上面例子里的
unbind函数,在控制器销毁时调用它,能避免不必要的内存泄漏。
内容的提问来源于stack exchange,提问作者fabOnReact
相关产品推荐
相关产品推荐

