Angular complex expression vs function in your markup - angularjs

Just wondering if there is a recommended solution for the following scenario.
I have a complex expression in my markup to show some error message, e.g.
ng-show="currentSection == 'pickup-from' && carHireEnquiryForm.pickUpLocation.$dirty && carHireEnquiryForm.pickUpLocation.$invalid && carHireEnquiryForm.pickUpLocation.$error.isLocation"
This can make the markup messy and hard to unit test, so to get around this I created a function for this, e.g.
ng-show="isShowError()"
Now the isShowError can easily be tested. Problem now is that the isShowError is invoked on every digest even if the element is not visible. This for me is even worst as performance it very important.
Is there a better way to achieve this? Is expressions the recommend way to do this? What if the expression had to include 20 statements? I am keen to reduce the amount of business logic in my markup as well.
Thanks in advance

There is not much of a difference between using function and expression, considering the fact that the function is also evaluated like an expression.
Implies if you are just using an expression, that too is being evaluated on every digest cycle. The function just add lightweight indirection.
As long as the expression evaluation is fast you can use either, but functions are better as they can encapsulate the validation logic.
The problem comes when we knowingly or unknowingly add some time consuming operation to the function, slowing down the function evaluation.

Related

React/JSX attrs w/strings vs braces

The docs say that a JSX attributes with strings are the same as attributes with braces...
<Thing attr='val' /> === <Thing attr={'val'} />
I thought I read something that said only use braces when needed because strings are more performant, but I can't find the reference now. Is there an evaluation cost for braces?
No there is no performance difference. Look at the code that's generated by each style:
<div first="abc" second={"def"}/>
// Compiles to:
React.createElement("div", { first: "abc", second: "def" });
Nicer to avoid unneeded braces though.
JSX is actually parsing it to a JS object anyway, so it's either string creation overhead for the parser or string creation overhead in your component. It's trivial either way. With a string literal, though, it's just visually noisy in the code. It only really serves a purpose if the val is a variable or expression.
There is, however, a perfomance hit in a templating engine, such as that employed by the new interpolated strings. E.g.:
`It is a ${'cat'}`
would be slower than:
`It is a dog`
which should be slower still than just a plain literal:
'It is a dog'
I'll leave it as an exercise for the reader to find the interpolation part in the JSX engine. ;) https://github.com/jsx/JSX/tree/master/src
Is there an evaluation cost for braces
Yes, As you can see anything inside {} will be considered as javascript code, so that will be executed , if you just want to assign the string then
just simply use the attr='val' rather than attr={'val'}
but if you have assignment condition based then you can use attr={'val'}
like
attr={ (condition) ? 'val1' : 'val2'}
I Hope , this will clear your thoughts.
For more details :
https://reactjs.org/docs/jsx-in-depth.html
Here you can read behind the scenes of string interpolation and speed performance :
https://koukia.ca/string-interpolation-vs-string-format-string-concat-and-string-builder-performance-benchmarks-c1dad38032a

Angular avoid function expression from running multiply times

I have multiply functions like count() getTotal(). All those calculation functions have to run if something changes my cart/object.
Currently I'm using them in the view like {{count()}}. So all those functions are running multiply times.
I think those functions are called multiply times, because of the dirty checking. Is this correct?
Now I read about the $watch function and that you should try to avoid it, because of performance issues. Anyway I wanted to test it, and $watchedmy cart. I found out it only logs a single time so wouldn't it be faster to $watch my cart and call all the calculations functions in there and then just bind to the result of the calculations?
I'm a bit confused know, cause i thought it would have the same behaviour. Because the $watch will also go through the digest loop.
I know there are already a lot of similiar questions, but having somebody explaining it directly for my case in a not so hard english, would make it a lot easier.
Example:
What has better performance? and why? Does both variants go through the digest cycle? Why then Variant 2 logs 10 times and Variant 1 only 1 time?
Variant 1
// bind these to scope and show like {{totalGross}}
cartService.totalGross = null;
cartService.totalNet = null;
cartService.totalItems = null;
// watch the cart here and update all variables
$rootScope.$watch(function () {
return cartService.cart;
}, function(){
cartService.totalGross = cartService.getCartTotalGross();
cartService.totalNet = cartService.getCartTotalNet();
cartService.totalItems = cartService.getTotalItems();
}, true);
Variant 2
// bind these to scope and show like {{getCartTotalGross()}}
cartService.getCartTotalGross();
cartService.getCartTotalNet();
cartService.getTotalItems();
Trying to answer my own question, altough i'm not shure if it's correct.
Variant 1 you have 1 more watcher, but we just watch values instead of functions and the 1 more because we watch the cart manually with $watch. But the watchers are less heavy to compute.
Variant 2 we are watching the value that functions are returning, so the functions have to calculate the same value multiply times, witch is more heavy. In each digest Cycle the UI get updated
Is this correct? So Variant 1 is better for performance?
It's generally considered bad practice to use $watch not (only) because it has performance issues, but because there are, most of the time, better alternatives (both clearer, and more efficient).
For example, instead of watching a model value that changes when the user enters something in an input, in order to compute something that depends on this value, you can use ng-change on the input and call the computation from there. This is faster, and the intent is clearer.
Now, to answer your question:
Every time an event is handled by angular, the event handler can modify anything in the scope. Angular has no way to know what has been modified. So it has to call, for example, getTotalItems() because an event handler might have changed something that makes the returned value of getTotalItems() change.
Additionally, changing any value that is watched causes a watcher function to be executed, and this watcher function can, in turn, change other values, that can be watched by other watchers, etc. etc. So angular needs to evaluate all the watched expressions in a loop, until it can be sure that the last evaluation leads to the same results as the previous one. That's what is known as the digest loop.
So, in short, having {{ getTotalItems() }} in the view is not a big deal if that function just returns something simple, like the length of an array, or the sum of a few values. But if it computes the meaning of life, it's a really bad idea, and you should instead compute the meaning of life only when it needs to be computed, and store the result in a variable that is displayed in the view.
You can do that with a watcher, but that should be the last resort. As I said already, there are often better alternatives.

Is it a bad practice to use function call in ng-if/*ngIf? [duplicate]

This question already has answers here:
angularjs ng-if difference between value and function
(2 answers)
Closed 7 years ago.
Is it a bad practice to use the return value of a function call inside ng-if. Will it affect the digest cycle/performance?
As any expression used in the view, it will be reevaluated at each digest cycle to see if its value has changed or not, and thus if the element must be removed or added to the DOM.
If the function is simple enough, no problem. If it tries to compute the 10000th decimal of pi, you'll have performance problems. What matters is to understand what you're doing, and how it works.
So if you feel using a function makes your code simpler, go for it, and start optimizing if you really need to.
No, that's just fine. The function shouldn't have side effects (especially not change other fields taking part in change detection)
Function calls will be slightly slower than just pure evaluation of a variable on scope due primarily to the fact that the step of "run function" must be handled before "check truthiness" is run on either. But this performance impact depends on how long your function takes to run.
Generally, anything that constitutes complex logic can be extracted out into a function and it will clean up your HTML since you won't need long JS in your template file.
I often extract to a function if the statement cannot be done in a single JS statement or if the statement starts being longer than about 40 characters.

Is there a reason to use $scope.$apply rather than $applyAsync?

What would be a use case for calling $scope.$apply rather than $applyAsync? I'm probably missing something, but the latter just seems like a safer version of the former, so you can't get digest reentrancy.
$scope.$apply will try to apply the given expression immediately, meaning that if a digest cycle is currently being run, you may end up getting an error/exception.
$applyAsync on the other hand will "schedule" the expression to be applied in about 10 milliseconds (as per the docs), so that you are able to queue more than one expression in the same digest cycle.

What is the time complexity for AngularJS's dirty checking algorithm?

While recently developing an AngularJS app I came across performance issues related to watches, digging down further makes me wonder what is the time complexity for the dirty checking algorithm using two-way data binding? From the looks of it, after every event there's a digest cycle, which inturn calls a watch cycle, so this must be O(n^2)... is this correct?
The dirty checking happens in the $diggest cycle, so we need to study the complexity of the $diggest cycle.
The $diggest cycle is the stage in which Angular ensures the changes of the model have settled,
so that it can render the view with the updated changes. In order to do that,
Angular starts a loop in which each iteration evaluates all the template expressions
of the view, as well as the $watcher functions of the $scope.
If in the current iteration the result is the same as the previous one,
then Angular will exit the loop. Otherwise, it will try again.
If after 10 attempts things haven't settled, Angular will exit
with an error: The "Infite $diggest Loop Error" (infdig).
Therefore the complexity of the dirty checking will deppend on the complexity of the functions that you have in the $watchers and in the expressions of your view (like your $filters).
So the $diggest cycle alone has a complexity of O(n) where n is the number o $watchers and template expressions that need to be iterated. But then you will have to consider the complexity of those functions. Also, notice that the $diggest cycle will always visit all those functions at least twice (in order to make sure that the changes have settled), so if you want to be more precise you could say that it has a complexity of at least O(n*2) and a maximum complexity of O(n*10), but since 2 is a constant value which its max number is 10 the complexity should still be considered O(n).

Resources