简体   繁体   中英

Is this a valid usage of @cached for autotracking of Ember Octane?

Recently I encountered an use case of @cached from tracked-toolbox when writing a Glimmer component with autotracking. Here is an example code snippet:

import Component from '@glimmer/component';

/**
 * Example usage
 * <PersonInfo
 *  @a={{this.objA}}
 *  @b={{this.stringB}}
 *  @c={{this.intC}}
 * />
 * Where objA can be a large object
 */

export default class PersonInfo extends Component {

  /**
   * I hope @cached here can help avoid re-running output getter in each
   * of the other getters, e.g. this.msg, this.link, this.name
   * But whenever any input args changes it triggers update 
   * (i.e. parent run this.objA = newObj)
   */
  get output() {
    return someExpensiveLogic(this.args.a, this.args.b, this.args.c);
  }

  get msg() {
    return translate(this.output.msg);
  }

  get link() {
    return convert(this.output.link);
  }

  get name() {
    return change(this.output.name);
  }
}
{{!-- In the template --}}
<div>
  {{this.name}}
  {{this.msg}}
  {{this.link}}
</div>

Without using @cached , the above code will execute the output getter 3 times when rendering, once for each of msg , link and name .

I also thought about building my own cache for output , but it requires me to manually keep track of which state is used and hash them, which could be expensive and hard to maintain.

From my understanding, what @cached provides is an access to the "global tag" in the auto tracking system, so I can rely on that tag to determine when the cache needs refresh.

Since this is not supported in a company project I work on for now, I hope this usage it can encourage us to add such support later.

Note: I found that @cached is convenient wrapper of

import { createCache, getValue } from '@glimmer/tracking/primitives/cache';

So fundamentally what I need is @glimmer/tracking/primitives/cache .

Posting a follow up here based on an offline discussion.

This is a valid usage of the @cached utility from tracked-toolbox . The narrow use case meets the below requirements:

  1. The output getter is expensive.
  2. The result of output is used multiple times in other getters in JS. (If this.output is only used directly in the template, it will already have exactly the same semantics around rerunning as it does with @cache .)
  3. Compared to an explicit cache of the values used in the output getter, using @cache will not evaluate changes of the arguments' values, which means if this.args.b is set to the same value as before, the output getter will still rerun. This is not a concern in this use case, because I know the parent will not set the same value in input args.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM