admin管理员组文章数量:1429841
If one changes a scope property first, and then broadcasts an event second, will the corresponding watcher callback and event listeners callback always be executed in that same order? For example:
$scope.foo = 3;
$scope.$broadcast('bar');
and elsewhere:
$scope.$watch('foo', function fn1(){...});
$scope.$on('bar', function fn2(){...});
Will fn1
always be executed prior to fn2
, or visa-versa, or can the order not be relied upon? Please cite sources, preferably to official angular docs.
In case it matters: lets assume the $scope.foo= and the $broadcast occur in a function invoked by an ng-click (i.e. user interaction)
[aside] Sorry question title is sloppy - please rename if you have something better.
If one changes a scope property first, and then broadcasts an event second, will the corresponding watcher callback and event listeners callback always be executed in that same order? For example:
$scope.foo = 3;
$scope.$broadcast('bar');
and elsewhere:
$scope.$watch('foo', function fn1(){...});
$scope.$on('bar', function fn2(){...});
Will fn1
always be executed prior to fn2
, or visa-versa, or can the order not be relied upon? Please cite sources, preferably to official angular docs.
In case it matters: lets assume the $scope.foo= and the $broadcast occur in a function invoked by an ng-click (i.e. user interaction)
[aside] Sorry question title is sloppy - please rename if you have something better.
Share Improve this question edited Dec 29, 2015 at 21:17 tom asked Dec 29, 2015 at 21:02 tomtom 2,2992 gold badges17 silver badges28 bronze badges 5- 1 Nothing official but I'm pretty sure that's all handled asynchronously so you cannot be guaranteed of any order. Race condition. – ryanyuyu Commented Dec 29, 2015 at 21:33
- @ryanyuyu thanks, that's my suspicion too. If the broadcast is called in a $timeout(fn, 0), can we be assured that the callback for the $on executes after then $watch callback? – tom Commented Dec 29, 2015 at 21:58
- I'm not sure there. It's possible that just lessens the effects of the race condition. Better to just chain promises. Or other callbacks. – ryanyuyu Commented Dec 29, 2015 at 22:44
- 1 right, a lessened race condition just makes it harder to find! Maybe I'll ask a separate question about that. – tom Commented Dec 29, 2015 at 22:51
- See my updated answer below. I am fairly certain the event handler gets called before the watch function. – Shaun Scovil Commented Dec 29, 2015 at 23:38
1 Answer
Reset to default 6To understand what is happening, you need to understand Angular's $digest cycle and event $emit and $broadcast functions.
Based on some research, I've also learned that Angular does not use any kind of polling mechanism to periodically check for model changes. This is not explained in the Angular docs, but can be tested (see this answer to a similar question).
Putting all of that together, I wrote a simple experiment and concluded that you can rely on your event handlers running first, then your watch functions. Which makes sense, because the watch functions can be called several times in succession during the digest loop.
The following code...
template.html
<div ng-app="myApp">
<div watch-foo ng-controller="FooController">
<button ng-click="changeFoo()">
Change
</button>
</div>
</div>
script.js
angular.module('myApp', [])
.directive('watchFoo', watchFooDirective)
.controller('FooController', FooController);
function watchFooDirective($rootScope) {
return function postLink(scope) {
scope.$watch(function () {
return scope.foo;
}, function (value) {
console.log('scope.$watch A');
});
scope.$on('foo', function (value) {
console.log('scope.$on A');
});
$rootScope.$on('foo', function (value) {
console.log('$rootScope.$on A');
});
$rootScope.$on('foo', function (value) {
console.log('$rootScope.$on B');
});
scope.$on('foo', function (value) {
console.log('scope.$on B');
});
scope.$watch(function () {
return scope.foo;
}, function (value) {
console.log('scope.$watch B');
});
};
}
function FooController($scope) {
$scope.foo = 'foo';
$scope.changeFoo = function() {
$scope.foo = 'bar';
$scope.$emit('foo');
};
}
...yields the following results in the console when the 'Change' button is clicked:
scope.$on A
scope.$on B
$rootScope.$on A
$rootScope.$on B
scope.$watch A
scope.$watch B
UPDATE
Here is another test that illustrates the watch callback being called twice in the digest loop, but the event handlers not being called a second time: https://jsfiddle/sscovil/ucb17tLa/
And a third test that emits an event inside the watch function, then updates the value being watched: https://jsfiddle/sscovil/sx01zv3v/
In all cases, you can rely on the event listeners being called before the watch functions.
本文标签: javascriptIn what order do angular watchers and event listeners executeStack Overflow
版权声明:本文标题:javascript - In what order do angular watchers and event listeners execute? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745507259a2661302.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论