Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to wait until multiple actions, triggered with one dispatcher, complete? #474

Open
ghost opened this issue Jun 6, 2016 · 17 comments
Open

Comments

@ghost
Copy link

ghost commented Jun 6, 2016

For example, i have one action Clear and many stores which are listening to it, how to do something only after Clear action is completed in all stores?

@devinivy
Copy link
Contributor

devinivy commented Jun 6, 2016

You may be interested in reflux ability to "join" actions: https://github.com/reflux/refluxjs#joining-parallel-listeners-with-composed-listenables

@ghost
Copy link
Author

ghost commented Jun 7, 2016

Can you give me some examples? It`s stupid question, but how to use reflux api? I mean how to call its methods.

@devinivy
Copy link
Contributor

devinivy commented Jun 7, 2016

It's not stupid at all! In this case you would create a store and create some actions. Stores have the ability to listen to actions. The "join" functionality is a feature of a store that allows it to listen to a composite of several actions. Here's a more complete example,

var Reflux = require('reflux');

var Actions = Reflux.createActions([
  'disarmBomb',
  'saveHostage',
  'recoverData'
]);

var gainHeroBadgeStore = Reflux.createStore({
  init: function() {
    this.joinTrailing(Actions.disarmBomb, Actions.saveHostage, Actions.recoverData, this.onBadge);
  },
  onBadge: function(data) {

    // Let store react to the events above having all taken place

    // Then notify everyone the store has updated
    // this.trigger();
  }
});

Actions.disarmBomb('warehouse');
Actions.recoverData('seedyletter');
Actions.disarmBomb('docks');
Actions.saveHostage('offices', 3);

@ghost
Copy link
Author

ghost commented Jun 7, 2016

i think, i have different case, i have many stores listening one action, but not one store listening many actions, thanks for the example, it`s very useful

@devinivy
Copy link
Contributor

devinivy commented Jun 7, 2016

If you have many stores listening to one action then it might look more like this,

var Reflux = require('reflux');

var Actions = Reflux.createActions(['disarmBomb']);

var FirstStore = Reflux.createStore({
  init: function() {
    this.listenTo(Actions.disarmBomb, this.onDisarm);
  },
  onDisarm: function(data) {

    // Let store react to the event having taken place

    // Then notify everyone the store has updated
    // this.trigger();
  }
});

var SecondStore = Reflux.createStore({
  init: function() {
    this.listenTo(Actions.disarmBomb, this.onDisarm);
  },
  onDisarm: function(data) {

    // Let store react to the event having taken place

    // Then notify everyone the store has updated
    // this.trigger();
  }
});

Actions.disarmBomb('warehouse');

@devinivy
Copy link
Contributor

devinivy commented Jun 7, 2016

Oh, I understand. You should also be able to listen to all stores. So if you have a store that wants to wait for some stores to trigger() after an action it might look like,

this.joinTrailing(Actions.disarmBomb, FirstStore, SecondStore, callback);

@ghost
Copy link
Author

ghost commented Jun 7, 2016

Wow, it`s exactly what i meant, thanks,
I think that those examples need to be included to documentation

Updated:

callback will be called for each action emmission, but i need it to be called only for the last emmission

i.e

var Actions = Reflux.createActions([
  'action'
]);

var Store1 = Reflux.createStore({
  listenables: [Actions],

  action: function () {
  //do something
  }
});

var Store2 = Reflux.createStore({
  listenables: [Actions],

  action: function () {
  //do something
  }
});

var Store3 = Reflux.createStore({
  init: function () {
    this.joinConcat(Actions.action, Store1, Store2, this.action);
  },

  action: function () {
    console.log('tadah');
  }
});

will cause 2 console logs

@ghost ghost closed this as completed Jun 7, 2016
@ghost ghost reopened this Jun 7, 2016
@ghost
Copy link
Author

ghost commented Jun 23, 2016

Is there anybody? Im still looking for answer)) I have found workaround by using callbacks in actions, it works, but its bad and unreadable

@devinivy
Copy link
Contributor

I don't quite understand. Can you expand your example to include the action call and store updates? Is the join working as described here?

@ghost
Copy link
Author

ghost commented Jun 29, 2016

The example is below, i need method action from Store3 to be invoked only when all dispatched actions completed, instead of being called for each action when it`s completed.
And yes, join works fine but not for my case.

@devinivy
Copy link
Contributor

What are the actions included in "all dispatched actions"?

@ghost
Copy link
Author

ghost commented Jul 1, 2016

An action from each store Store1 and Store2

@semikolon
Copy link

joinTrailing should do the job, as explained above

@BryanGrezeszak
Copy link
Contributor

BryanGrezeszak commented Nov 19, 2016

If I understand the issue correctly, would a simple postEmit function (as in a counterpart to the preEmit that already exists) solve this?

So something like:

var Actions = Reflux.createActions(['doAction']);

Actions.doAction.postEmit = function()
{
    console.log('the action is done emitting');
}

Obviously it's kinda impossible to figure out whether whatever you're doing inside your stores on that action is complete (because for all we know you could be starting a 24 hour setTimeout inside there or something, and that's not Reflux's business to know or care) but it would be able to tell you when the action had finished emitting to all of your stores (i.e. all the onDoAction or whatever functions within them will have been called).

@ghost
Copy link
Author

ghost commented Nov 19, 2016

Sorry for not responding so long, i ended up using redux instead of reflux, at least it support promises
all i needed is something similar to Promise.all([Action1(), Action2(), Action3(), ...])

@ghost ghost closed this as completed Nov 19, 2016
@BryanGrezeszak
Copy link
Contributor

BryanGrezeszak commented Nov 19, 2016

My bad. I thought you said that you had a situation where you had 1 action and many stores listening and needed to know when that action was emitted to all stores.

Either way, returning promises on an action call sounds good. I'm gonna look into adding that.

@BryanGrezeszak
Copy link
Contributor

Reopened. The fact that the original asker moved on does not resolve the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants