machty / ember-concurrency-decorators

Task decorators for ember-concurrency 1.x (merged into ember-concurrency 2.0)
MIT License
70 stars 25 forks source link

Support Decorators in Encapsulated Tasks #37

Open spencer516 opened 5 years ago

spencer516 commented 5 years ago

This may be a better issue for Ember Concurrency itself (as I suspect this request would require some plumbing there given neither TaskInstance nor TaskProperty are public API), but since it's in the vein of decorators, I thought I'd start here.

While we have support for Encapsulated Tasks with Decorators (this PR), the "encapsulated object" itself is not a class I can add decorators to.

Let's say I have a "countdown" task that I reuse in a bunch of different components in my app. In the old non-class-based decorator world, I might write this utility like so:

export default task({
  startValue: 0,
  currentValue: 0,

  percentComplete: computed('{startValue,currentValue}', function() {
    return 1 - this.currentValue / this.startValue;
  }),

  *perform(startValue = 100) {
    set(this, 'startValue', startValue);
    set(this, 'currentValue', startValue);

    while(this.currentValue > 0) {
      yield timeout(1000);
      set(this, 'currentValue', this.currentValue - 1);
    }
  }
});

But, in the world of Classes & Decorators, it might be nice to express this with all the modern goodies. Perhaps it'd look something like:

export default class CountdownTask extends TaskInstance {
  currentValue = 0;
  startValue = 0;

  @computed('{currentValue,startValue}')
  get percentComplete() {
    return 1 - this.currentValue / this.startValue;
  }

  *perform(startValue = 100) {
    set(this, 'startValue', startValue);
    set(this, 'currentValue', startValue);

    while(this.currentValue > 0) {
      yield timeout(1000);
      set(this, 'currentValue', this.currentValue - 1);
    }
  }
}

(Let me know if I should move this issue — and happy to contribute to making this happen if it makes sense)

buschtoens commented 5 years ago

That's a really good suggestion. Sorry for answering only just now; this must have fallen through the cracks.

I think this could be possible without changes to ember-concurrency, but wouldn't be as performant.