How do you manage asynchronous Store operations with Flux?
Asked Answered
C

2

30

In the Facebook talk on the Flux architecture, Jing mentions at 12:17 that the dispatcher enforces that no actions can be dispatched until the current action is fully processed by the stores.

https://static.mcmap.net/file/mcmap/ZG-AbGLDKwfpaVbQdVf0cGyiXS2jaRA/vi/nYkdrAPrdcw/0.jpg

The dispatcher here is the main piece that enforces that there's no cascading effects; once an action goes into the store, you can't put another one in until the stores are completely finished processing it.

My question, then, is how do you properly deal with long-running asynchronous operations that might be kicked off from the store (e.g. an Ajax request, or dealing with some other outside async API)—anything that blocks the completion of the action dispatch (for instance, waiting to resolve a promise with the result of an Ajax request) could block UI-generated actions from the user from being dispatched.

Compound answered 13/5, 2014 at 15:51 Comment(0)
S
30

In my understanding, asynchronous actions that rely on Ajax, etc. shouldn't block the action from being dispatched to all subscribers.

You'll have a separate action for the user action, like TODO_UPDATE_TEXT in the TodoMVC example and one that gets called when the server returns, something like TODO_UPDATE_TEXT_COMPLETED (or maybe just something more generic like TODO_UPDATE_COMPLETED that contains a new copy of the latest attributes).

In cases where you want to do optimistic updates to show the user the effects of their change immediately, you can update the store in response to the user action immediately (and then once again when the server returns with the authoritative data). If you want to wait on the server, you can have the store only update itself in response to the server-triggered actions.

Sheathing answered 13/5, 2014 at 17:3 Comment(3)
Suppose the update fails and the server returns an error message that you'd like to display. In the TODO_UPDATE_FAILED handler, would you save the error message in the todo store?Incontinent
@Incontinent You need to ask yourself if that error message needs to be stored in the TodoStore. If not then as a suggestion you should create a seperate data store for error messages that in turn will be used by components that handles error messages (such as a alert message component).Unrivaled
Breaking one task with multiple actions can mess things up, if two or more such tasks intertwine with each other, what's the best practice to avoid it?Patricide
G
2

See the implementation of what Sophie explains in this fluxxor example of dealing with asynchronous data. A negative point is that following this approach, each user interaction requires three actions (trigger, success and fail) but maybe not all your user interactions require this optimistic approach.

The important part is in the action:

loadBuzz: function() {
  this.dispatch(constants.LOAD_BUZZ);

  BuzzwordClient.load(function(words) {
    this.dispatch(constants.LOAD_BUZZ_SUCCESS, {words: words});
    }.bind(this), function(error) {
    this.dispatch(constants.LOAD_BUZZ_FAIL, {error: error});
    }.bind(this));
  },

BinaryMuse (fluxxor creator) dispatches the LOAD_BUZZ action and then triggers the asynchronous request with the success and fail functions, where dispatches the success or fail action. The stores can listen to LOAD_BUZZ action for a optimistic update or display an svg loading icon, and then listen to the success and error actions for a final notification of success or error (plus save the BUZZWORD in the store).

onLoadBuzz: function() {
  this.loading = true;
  this.emit("change");
},

onLoadBuzzSuccess: function(payload) {
  this.loading = false;
  this.error = null;

  this.words = payload.words.reduce(function(acc, word) {
    var clientId = _.uniqueId();
    acc[clientId] = {id: clientId, word: word, status: "OK"};
    return acc;
  }, {});
  this.emit("change");
},

I think like Sophie that ajax requests shouldn't block the action from being dispatched, because this would be more like a synchronous request to the server and the responsiveness of the page would be affected.

Gittens answered 5/5, 2015 at 12:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.