ember-concurrency: Does not work with native classes
Using Ember 3.6, ember-concurrency 0.8.26
Given a component defined with ‘classic’ syntax, all is good.
import Component from '@ember/component'
import { task, timeout } from 'ember-concurrency';
export default Component.extend({
result: null,
doStuff: task(function*(){
yield timeout(1000);
this.set('result', 'done');
})
});
If, however, we use native class syntax
import Component from '@ember/component';
import { task, timeout } from 'ember-concurrency';
export default class NativeTaskComponent extends Component {
result = null;
doStuff = task(function*() {
yield timeout(1000);
this.set('result', new Date());
});
}
We see -task-property.js:620 Uncaught Error: It looks like you tried to perform a task via this.nameOfTask.perform(), which isn't supported. Use 'this.get('nameOfTask').perform()' instead.
I’ve spent a little time trying to figure out why this is the case and have found that when creating a TaskProperty, the function passed to super
does not get executed https://github.com/machty/ember-concurrency/blob/master/addon/-task-property.js#L416-L437
export class TaskProperty extends _ComputedProperty {
constructor(taskFn) {
let tp;
console.log('called before super');
super(function(_propertyName) {
console.log('called inside super anonymous function');
taskFn.displayName = `${_propertyName} (task)`;
...
The transpiled output of the classic invocation is
define("dummy/components/classic-task/component", ["exports", "ember-concurrency"], function (_exports, _emberConcurrency) {
"use strict";
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.default = void 0;
var _default = Ember.Component.extend({
result: null,
doStuff: (0, _emberConcurrency.task)(function* () {
yield (0, _emberConcurrency.timeout)(1000);
this.set('result', 'done');
})
});
_exports.default = _default;
});
Whilst the native version is
define("dummy/components/native-task/component", ["exports", "ember-concurrency"], function (_exports, _emberConcurrency) {
"use strict";
Object.defineProperty(_exports, "__esModule", {
value: true
});
_exports.default = void 0;
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
class NativeTaskComponent extends Ember.Component {
constructor(...args) {
super(...args);
_defineProperty(this, "result", null);
_defineProperty(this, "doStuff", (0, _emberConcurrency.task)(function* () {
yield (0, _emberConcurrency.timeout)(1000);
this.set('result', new Date());
}));
}
}
_exports.default = NativeTaskComponent;
});
So it looks like it’s caused by the way the property ends up being defined on the native class that is causing the issue.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 17 (9 by maintainers)
Commits related to this issue
- Add some brief documentation on use with Octane/decorators Raised in issue #271, there is currently no official documentation on using ember-concurrency with native classes and other Octane-related u... — committed to machty/ember-concurrency by maxfierke 5 years ago
- Add some brief documentation on use with Octane/decorators Raised in issue #271, there is currently no official documentation on using ember-concurrency with native classes and other Octane-related u... — committed to machty/ember-concurrency by maxfierke 5 years ago
For completeness sake: In the Octane edition of Ember.js, you can create a task like this:
Hmm, I’m seeing the “classic” syntax generating that error:
Class constructor ComputedProperty cannot be invoked without 'new'
:References (-task-property.js:398):
OK, perhaps it’s worth updating the docs to reflect that, as this issue is likely to come up more frequently as the community marches forward
@gabrielgrant That is correct, thanks! I updated the snippet. 😃
Pretty sure you are running into #262 and #265, which is why making sure you are on the latest version of ember-concurrency fixed it. 😊
Closing this out, since documentation has been added on using with native classes on Ember 3.10+. More specific issues w/ native classes, decorators, etc. can be addressed in separate issues as needed in the future.
I’d support adding the
@task(function*() {})
syntax to the official docs, as @jenweber suggested.We can also mention
ember-concurrency-decorators
as an alternative. Related: #326Could we start by adding an example to the Task Function Syntax page? Or do we also need to cover the caveats/edge cases for it to be merged?
Example gist: https://gist.github.com/jenweber/443dac9876c7ef2b1115093cfd5d6fac
The three solutions are:
.extend({ })
block, likedefineProperty
, which has performance implications