$apply in setTimeout

谁都会走 提交于 2020-01-17 07:32:05

问题


I konw that $apply used to connect the Javascript context and the AngularJS context.

A simple example is below:

template:

<div>{{someVal}}</div>

javascript in controller:

setTimeout(function() {
    scope.$apply(function(){scope.someVal = 123});
}, 1000);

We need use $apply in above situation.

First Qustion:

If I modify javascript above to:

setTimeout(function() {
    scope.someVal = 123;
}, 1000);

scope.$watch('someVal', function(val) {
    console.info(someVal);
});

No console about someVal modified to 123... Why? Can't we watch expression modified in timeout callback?

Second Question:

If we use ngSwitch directive like below:

<div ng-switch on="sub">
    <div ng-switch-when="a">
//state a
    </div>
    <div ng-switch-when="b">
//state b
    </div>
</div>

When I modify the sub in controller:

scope.sub = 'a';
setTimeout(function() {
    scope.sub = 'b';
}, 1000);

No need to use $apply!!!! Why?

I found that ngSwitch directive use $watch to monitor on attribute value. Why ngSwitch can watch scope attribute modified in timeout callback?????

Pls tell me the reason about the 2 qustions above.


回答1:


From AngularJs documentation

$apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the angular framework we need to perform proper scope life cycle of exception handling, executing watches.

window.setTimeout is a JavaScript function, so whatever you use setTimeout you must use $apply() to update the model.

Your second example wouldn't work without $apply(), I've made a demo to clarify the $watch and $apply issue. Please check it.




回答2:


You can use $timeout that is a wrapper for window.setTimeout and also this way you wont need to use $apply on the callback:

$timeout(function() { scope.someVal = 123; }, 1000);

When you run code that is outside Angular, you'll need a way to let the Angular and the watchers of that value, to know that it has changed. Thats what $apply is for, it will allow watch listeners to fire

About you second question, of why the scope is updating without a $apply, you should be firing indirectly somehow a $apply/$digest. To give you a more specific answer, a Plunker will be necessary to check what else in going on on your code.




回答3:


Use the Angularjs $timeout service instead of setTimeout and you will not require $apply. Same thing is if you are using a jquery http call, use the angular http service to avoid using $apply.



来源:https://stackoverflow.com/questions/21472327/apply-in-settimeout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!