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
691 stars 157 forks source link

Feature request - New attribute @runOnce - for tasks that should run only once #417

Open ondrejsevcik opened 3 years ago

ondrejsevcik commented 3 years ago

Hi,

in our app, we use following pattern where we load data only once quite a lot.

Here is an example

// services/user-session.js
loadData: task(...).drop(),

async loadOnce() {
  if (this.loadData.last || this.loadData.isRunning) {
    await this.loadData.last;
    return;
  }
  await this.loadData.perform();
  return;
}

and then in our components and routes, we can call await userSession.loadOnce() and do not worry to make accidentally multiple requests against our server.


It would be nice to have this baked-in into this library so that we can just add this modifier directly on the task itself.

loadData: task(...).runOnce(); // could be also called .onlyOnce()

What do you think?

maxfierke commented 3 years ago

One thing I've seen before is adding the check within the task, something like:

@dropTask *myTask() {
  if (this.myTask.lastSuccessful?.value) {
    return this.myTask.lastSuccessful?.value;
  }

  // ... other stuff
}

This will basically ensure the same result is carried forward every time the task runs. If you were to run cancelAll({ resetState: true }) on the task, you would then clear out the lastSuccessful state and be able to recompute it, if that's useful too.

I'm working on an RFC for user-definable modifiers, and this seems like maybe a good space for that, rather than inclusion within core ember-concurrency, as I'm not sure how broadly applicable it is, other than the one-time data loading case. (I do think it's useful though!)