admin管理员组

文章数量:1399260

Is calling a computed signal within a loop bad practice?

Should I be avoiding this:

const filtered = computed(() => {
  return listItems.filter(item => item.name.includes(searchString())
});

and instead always do this:

const filtered = computed(() => {
  const search = searchString();
  return listItems.filter(item => item.name.includes(search)
});

I just did a quick performance test as follows:

const someComputation = computed(() => ...)
const before = performance.now();
for (let i = 0; i < 10000; i++)
  someComputation();
console.log(`Time taken: ${performance.now() - before}`)

This performs very well. The above code logs 5 (as in 5 milliseconds). As we know, Angular is caching previous results and not recomputing if none of the computed signals dependencies change.

Is calling a signal in a loop considered a code-smell? Is it bad practice and to be avoided out of principle?

Is calling a computed signal within a loop bad practice?

Should I be avoiding this:

const filtered = computed(() => {
  return listItems.filter(item => item.name.includes(searchString())
});

and instead always do this:

const filtered = computed(() => {
  const search = searchString();
  return listItems.filter(item => item.name.includes(search)
});

I just did a quick performance test as follows:

const someComputation = computed(() => ...)
const before = performance.now();
for (let i = 0; i < 10000; i++)
  someComputation();
console.log(`Time taken: ${performance.now() - before}`)

This performs very well. The above code logs 5 (as in 5 milliseconds). As we know, Angular is caching previous results and not recomputing if none of the computed signals dependencies change.

Is calling a signal in a loop considered a code-smell? Is it bad practice and to be avoided out of principle?

Share Improve this question edited Mar 25 at 12:09 jonrsharpe 122k30 gold badges268 silver badges475 bronze badges asked Mar 25 at 9:04 Stephen PaulStephen Paul 39.1k18 gold badges98 silver badges76 bronze badges 2
  • 1 In what case would you do this? – leonardkraemer Commented Mar 25 at 9:25
  • 2 Provided searchString() cannot change during the loop it should be safe (please check). Even if it can not change in current angular having one less line still feels like an unnecessary optimization that makes the code harder to read, possibly introduce hard to debug bugs in the future and will be optimized by the minifier/optimizer/branch predictor anyway. – leonardkraemer Commented Mar 25 at 10:56
Add a comment  | 

2 Answers 2

Reset to default 1

Calling a computed signal within a loop is not inherently bad practice but it really depends on how the dependencies of the signal behave and how the loop interacts with them.

you have to consider some things:

  • If the computed signals dependencies remain stable within the loop, calling it is fine.

  • If the computation includes signals that may change during iteration it can lead to unnecessary recalculations

given your example:

const filtered = computed(() => {
  return listItems.filter(item => item.name.includes(searchString()));
});

the searchString() is a signal dependency here. As long as searchString() doesn't change, filtered() always returns the cached value. However every iteration might trigger the searchString() function call inside the filter loop, potentially causing unnecessary reads.

so your alternative would definitely be the better practice in some cases:

const filtered = computed(() => {
  const search = searchString(); // Read signal **once**
  return listItems.filter(item => item.name.includes(search));
});

Now, searchString() is called once per computation, avoiding multiple function calls inside the filter() which is more efficient when filter is run frequently or on larger datasets.

so the best practice would be to extract signal values outside loops or performance-critical sections when possible.

It's exactly the same. Internally computed signals are checking if the node should be recalculated or not - if it should, the computed signal switches to COMPUTING state and recalculates the result. It even does not matter if the searchString is yet another computed signal (same reason as its parent). There is a slight performance loss in the second version, but its probably very minor, though it depends if the searchString is computed or "classic" signal; latter will require getter to run instead of just reading the value from the variable.

Regarding code-smell, it all depends on the readability of the code or what makes sense at that moment. If there are a lot of signals inside of the computed signal it might make more sense to put them at the beginning of the callback, but again that boils down to preference/occasion.

You can inspect the source code of the Computed signal here:

  • https://github/angular/angular/blob/main/packages/core/primitives/signals/src/computed.ts

本文标签: angularIs it bad practice to call a computed signal from within a loopStack Overflow