Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$evalAsync does not always get executed in the current $digest cycle (1.0.0rc8) #947

Closed
tbosch opened this issue May 9, 2012 · 7 comments
Assignees

Comments

@tbosch
Copy link
Contributor

tbosch commented May 9, 2012

Hi,
when I have a scope that contains a single $watch, which uses $evalAsync, then the $evalAsync does not get executed until the next $digest cycle, but not in the current $digest cycle.

Here is a jsfiddle to show the problem: http://jsfiddle.net/GGbzx/1/

When you type a character into the textbox, the $watch fires and logs the current value using $evalAsync to the console.
However, in this case, the value that is logged is not the current value of the input field, but the last value (e.g. type in "aaa", then the log only shows "aa".

Tobias

@tbosch
Copy link
Contributor Author

tbosch commented May 9, 2012

Sorry, this example is not right: It shows the old value because I use the wrong argument from the watch callback...

@tbosch
Copy link
Contributor Author

tbosch commented May 9, 2012

Ok, here is a better example: http://jsfiddle.net/GGbzx/3/

A button increments a value on the $scope.
And there is a watcher on the $scope using a function as expression ($watch(function()...), which outputs the current value using $evalAsync to the console.

When you click the button to increment the counter, the $evalAsync is no more executed in the same $digest.

Tobias

Everything works if you:

  • Remove the <div ng-controller="EmptyCtrl">
  • Use a $watch(counter, ...) instead of a $watch(function())
  • Put a <input type="text" ng-model="counter"> in the html

Tobias

@ghost ghost assigned IgorMinar May 9, 2012
@IgorMinar
Copy link
Contributor

right the first fiddle incorrectly interpreted the order of arguments in the watch callback: http://jsfiddle.net/IgorMinar/GGbzx/4/

I'm looking at the second fiddle now

@IgorMinar
Copy link
Contributor

this is not a bug. eval async does get executed, at the correct time, but the value you print is stale because it's a copy of the counter that is done in the watch fn.

@IgorMinar
Copy link
Contributor

I'm actually happy that your example doesn't blow up - at first look I would expect it to fail with infinite digest error.

The problem with your code is that your watch fn is not idempotent. The side-effect it has is the $evalAsync registration. This is a programming/design error in your code. Does your app suffer from the same issue or is there something else going on?

@IgorMinar
Copy link
Contributor

I'm going close this bug. If you can repro it with idempotent watch fn then I'll be happy to reopen it and investigate further.

@tbosch
Copy link
Contributor Author

tbosch commented May 29, 2012

Sorry for the late reply.
I didn't know that the watch function is not allowed to have side effects. I read the source code of ng-repeat, which does all of the repeating logic in a watch function...

Thanks for investigating this.
Tobias

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants