ember-concurrency: Does not work with Octane

repro repo: https://github.com/NullVoxPopuli/octane-ember-concurrency-repro

npx ember-cli new my-app -b @ember/octane-app-blueprint --yarn
cd my-app
yarn ember install ember-concurrency

with the templtae:

<div {{did-insert (perform this.myTask)}}>
  boop
</div>
import Component from '@glimmer/component';
import { task } from 'ember-concurrency';

export default class MyComponent extends Component {
  @task myTask = function*() {
    console.log('my task');
  }
}

Uncaught (in promise) Error: Assertion Failed: The first argument passed to the `perform` helper should be a Task object (without quotes); you passed undefined

and then with ember-concurrency-decorators:

Uncaught (in promise) Error: Assertion Failed: @computed can only be used on empty fields. myTask has an initial value (e.g. `myTask = someValue`)

with this preferred syntax:

  @task * myTask() {
    console.log('my task');
  }

we get a babel error:

✖ 1 problem (1 error, 0 warnings)

Build Error (broccoli-persistent-filter:Babel > [Babel: e-concurrency]) in e-concurrency/components/my-component.js

.../components/my-component.js: Unexpected token (6:19)

  4 | 
  5 | export default class MyComponent extends Component {
> 6 |   @task * myTask() {
    |                    ^
  7 |     console.log('my task');
  8 |   }
  9 | 

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 17 (7 by maintainers)

Most upvoted comments

looks like this is the current way to use generators with decorators:

import Component from '@glimmer/component';
import { task } from 'ember-concurrency';

export default class MyComponent extends Component {
  @task(function*() {
    console.log('my task');
  }) myTask;
// ...

Just adding to @muziejus comment… if you have a task that you use in multiple places:

Image 2019-09-09 at 5 52 35 PM

Just adding to @NullVoxPopuli’s comment, if someone were to come here looking for a solution. To append a method like restartable, one more extra set of parentheses is needed:

import Component from '@glimmer/component';
import { task } from 'ember-concurrency';

export default class MyComponent extends Component {
  @(task(function*() {
    console.log('my task');
  }).restartable())
  myTask;
// ...

Not sure where I picked this up, but hopefully it’ll help someone else.

I don’t think I need ember-concurrency-decorators anymore?

You don’t need it anymore, if

  • you are fine with the @task(function*() { ... }) myTask; syntax for the interim period and
  • you are not using TypeScript / don’t care about type errors concerning tasks. The issue I linked above would allow you to use ember-concurrency with TypeScript in a type-safe way.

but yeah, a month ago, the @task * myTask {} syntax worked, and now it doesn’t. I think it may be a babel regression?

Definitely sounds like it! Might also be that this is now somehow caused by using stage 1 decorators again? 🤔

@wagenet just to keep you in the loop: yes, it’s a Babel bug in the stage 1 transforms. But there’s already a PR to fix it waiting to be merged. More details: https://github.com/machty/ember-concurrency-decorators/issues/48

I think I’ve given up on type safety on tasks until decorators hit stage 3/4. dat : any lyfe. 😦 haha