admin管理员组

文章数量:1325594

I've recently learned about Redux.
I well understood the concept but I don't figure out this line in the official documentation:

Because all changes are centralized and happen one by one in a strict order, there are no subtle race conditions to watch out for.

How can Redux guarantee no subtle race conditions?

Indeed, I can imagine this scenario (in order):

  1. Some ponent dispatches ACTION_TYPE_1.
  2. Some ponent dispatches ACTION_TYPE_2.
  3. ACTION_CREATOR_1 makes an ajax call to grab some data.
  4. ACTION_CREATOR_2 makes an ajax call to grab some data.
  5. ACTION_CREATOR_2 treats grabbed data before ACTION_CREATOR_1 does.
  6. Possible weird behavior due to this race condition?

So actions creators dispatching would be applied in order, but implementations of those actions creators might not apply in order, possibly leading to non-deterministic code.

How to figure out the quote?

I can understand that with Redux, there's a kind of trace about dispatched actions' history (helping to understand the program workflow at runtime), but what about the real implementations of those actions?

I've recently learned about Redux.
I well understood the concept but I don't figure out this line in the official documentation:

Because all changes are centralized and happen one by one in a strict order, there are no subtle race conditions to watch out for.

How can Redux guarantee no subtle race conditions?

Indeed, I can imagine this scenario (in order):

  1. Some ponent dispatches ACTION_TYPE_1.
  2. Some ponent dispatches ACTION_TYPE_2.
  3. ACTION_CREATOR_1 makes an ajax call to grab some data.
  4. ACTION_CREATOR_2 makes an ajax call to grab some data.
  5. ACTION_CREATOR_2 treats grabbed data before ACTION_CREATOR_1 does.
  6. Possible weird behavior due to this race condition?

So actions creators dispatching would be applied in order, but implementations of those actions creators might not apply in order, possibly leading to non-deterministic code.

How to figure out the quote?

I can understand that with Redux, there's a kind of trace about dispatched actions' history (helping to understand the program workflow at runtime), but what about the real implementations of those actions?

Share Improve this question edited Dec 11, 2016 at 3:24 Mik378 asked Dec 11, 2016 at 0:38 Mik378Mik378 22.2k15 gold badges91 silver badges190 bronze badges 9
  • 2 JavaScript is single-threaded, therefore no race conditions. – castletheperson Commented Dec 11, 2016 at 0:42
  • 1 Yes I know, but what about parallel promises resolution for instance? – Mik378 Commented Dec 11, 2016 at 0:44
  • What do you mean by parallel? Single-threaded means only one promise can resolve at a time. – castletheperson Commented Dec 11, 2016 at 0:46
  • In this article: medium./javascript-scene/…, there's this sentence: "When a newbie thinks about creating a view, they might think, “This bit needs the user model, so I’ll launch an async request to fetch that and when that promise resolves, I’ll update the user ponent with their name. That bit over there requires the to-do items, so we’ll fetch that, and when the promise resolves, we’ll loop over them and draw them to the screen.” (=> potential race conditions) Redux would solve this issue.. I can't figure out how. – Mik378 Commented Dec 11, 2016 at 0:53
  • 1 @4castle: the result of an action can be asynchronous. E.g.: when doing an ajax-call or whatever. Therefore the responses of actions 1 and 2 can be out of order. Single-threadedness notwithstanding. – Geert-Jan Commented Dec 11, 2016 at 1:11
 |  Show 4 more ments

2 Answers 2

Reset to default 4

I've just came across this point, very meaningful, by @DanAbramov himself.

I think it well answers to my OP.

The point is that as long as dispatching of actions remains synchronous (despite that actions creators internal process might not be synchronous at all), it's easy to figure out quickly about a race condition (or other issues regarding non-determinism) by establishing and logging an history of dispatched actions.
Especially it's easy to reproduce the "weird" state to then figure out how to avoid it (like Event-Sourcing).

Without any synchronous and visible point in time, it would be very hard to master what happened; that's why Redux brings a benefit.

Redux does not avoid race conditions, but does reduce drastically subtle (hard to analyse) race conditions, as documentation states.

  1. Javascript is thread safe so 2 functions cannot run at the same time.

  2. Redux does not know about asynchronous operations, it only cares about the current state, events that are dispatched to it and how to transition current state to some other state given an event.

  3. Thus ensuring action dispatching order is your responsibility, it's not a responsibility of Redux.

  4. If there are two events, X and Y, and you want to prevent handling Y before X is handled, then you can trace it in your Redux state using some state properties. Thus you can easiliy prevent handling Y before X is handled.

  5. There are too many different requirements for asynchronous operations and error handling people may wish to apply. Thus it is difficult to provide a general solution for "race conditions" you are talking about.

  6. Design your system, find all edge cases, and create a new event/event name/event handling for each edge case you can have. Then handle them in your redux reducer, make proper state transitions. In Web applications, nothing is a deadly error (it's not a good UI/UX to ask users to refresh their browsers) so you must recover from every possible edge case, thus throwing errors don't make much sense.

本文标签: javascriptHow can Redux guarantee no race conditionStack Overflow