machty / ember-concurrency

ember-concurrency is an Ember Addon that enables you to write concise, worry-free, cancelable, restartable, asynchronous tasks.
http://ember-concurrency.com
MIT License
689 stars 157 forks source link

how to share tasks between two components "detected a potentially hazardous "self-cancel loop" #320

Open st-h opened 5 years ago

st-h commented 5 years ago

given a component, which displays a modal dialog (for instance a prompt wether a record should be deleted). When the delete button is pressed, it should display a running indicator until the operation is complete. So, we have something like this:

modal-dialog.hbs:

{{#if ok.isRunning}}
  <Spinner />
{{else}}
  <button {{action (perform ok)}}>delete</button>
{{/if}}

modal-dialog.js:

export default Component.extend({
  ok: task(function * () {
    yield this.delete();
    this.hide();
  }),
  delete() { }
});

Then we have another component/controller that includes the dialog and has a task to actually delete the record: hbs:

{{modal-dialog delete=(perform delete)}}

js:

delete: task(function * () {
  yield this.version.destroyRecord();
  // do some more stuff
})

This displays the following warning:

ember-concurrency detected a potentially hazardous "self-cancel loop" between parent task _ok and child task deleteVersion. If you want child task deleteVersion to be canceled when parent task _ok is canceled, please change .perform() to .linked().perform(). If you want child task deleteVersion to keep running after parent task _ok is canceled, change it to .unlinked().perform()

and seems to cancels all following statements after the yield statement.

I haven't been able to find out how linked or unlinked is supposed to work in this situation, as there is no actual {{linked}} helper, which could be used similar to the way perform is currently used.

Could you please provide some details how ember concurrency tasks can be shared between two components - similar to what can easily be done with plain ember actions? Or how do I get rid of this warning?

st-h commented 5 years ago

Not sure if this is the best solution, however using an async function with await for the child task seems to solve the issue:

async delete() {
  await this.version.destroyRecord();
  // do some more stuff
}