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

Decorator for aliasing the last value #12

Closed alexlafroscia closed 5 years ago

alexlafroscia commented 6 years ago

I find myself using this pattern a lot in my code:

class Foo
  @task
  someTask = function*() { /* whatever */ };

  @alias('someTask.lastSuccessful.value')
  someTaskValue;
}

I came up with a little helper that just removes the need to add the lastSuccessful.value bit to the end, and allows an option for providing a default value. Would you be interested in adding the helper to this project? Or do you want to keep the decorators to just task definition?

buschtoens commented 6 years ago

I find myself doing this a lot too!

What would your proposed API look like?

alexlafroscia commented 6 years ago

The simple little decorator I made looks like this:

class Foo
  @task
  someTask = function*() { /* whatever */ };

  @lastValue('someTask')
  someTaskValue;
}

You can also provide a default value, if the task returned something that isNone or hasn't been run yet. I found this useful when passing a task's value into something validated with @ember-decorators/argument that is expecting an array, that I didn't want to make optional

class Foo
  @task
  someTask = function*() { /* whatever */ };

  @lastValue('someTask', { default: 'foo' })
  someTaskValue;
}

Or, in cases like returning a non-primitive where you don't want to potentially leak the same object that could be mutated, you can provide a factory function for creating the default (which supersedes the default if both happened to be provided:

class Foo
  @task
  someTask = function*() { /* whatever */ };

  @lastValue('someTask', { defaultFactory: () => ({}) })
  someTaskValue;
}

I'll make the PR so we can talk more concretely about it, if that's helpful -- just didn't want to take the effort if it would be rejected on principle.