How to deal with race conditions in event listeners and shared state?

谁说胖子不能爱 提交于 2020-04-18 05:47:54

问题


I have 2 event listeners that operate on the same shared data/state. For instance:

let sharedState = {
  username: 'Bob',
  isOnline: false,
};

emitter.on('friendStatus', (status) => {
  sharedState.isOnline = status.isOnline;
});

emitter.on('friendData', (friend) => {
  if (sharedState.isOnline) {
    sharedState.username = friend.username;
  }
});

My problem is that these events are emitted at any order. The friendData event might come in before the friendStatus. But friendData does something with the data returned from friendStatus. In other words: I need the event handler for friendData to execute after friendStatus, but I don't have this assurance from the event emitter perspective. I need to somehow implement this in my code.

Now of course I could simply remove the if (sharedState.isOnline) { from the friendData listener and let it run its course. Then I'd have a function run after both handlers have finished and somewhat reconciliate the shared state dependencies:

emitter.on('friendStatus', (status) => {
  sharedState.isOnline = status.isOnline;
  reconcileStateBetweenUsernameAndIsOnline();
});

emitter.on('friendData', (friend) => {
  sharedState.username = friend.username;
  reconcileStateBetweenUsernameAndIsOnline();
});

Problem is that this reconciliation function knows about this specific data dependencies use case; hence cannot be very generic. With large interconnected data dependencies this seems a lot harder to achieve. For instance I am already dealing with other subscriptions and other data dependencies and my reconciliation function is becoming quite large and complicated.

My question is: is there a better way to model this? For instance if I had the assurance that the handlers would run in a specific order I wouldn't have this issue.

EDIT: expected behavior is to use the sharedState and render a UI where I want the username to show ONLY if the status isOnline is true.


回答1:


From @Bergi's answer in the comments the solution I was hinting seems to be the most appropriate for such case. Simply let the event-handlers set their own independent state, then observe on the values changing and write appropriate logic based on what you need to do. For instance I need to show a username; this function shouldn't care about the order or have any knowledge of time: it should simply check whether the isOnline status is true and if there's a username. Then the observable pattern can be used to call this function whenever each dependency of the function changes. In this case the function depends on status.isOnline and friend.username hence it will observe and re-execute whenever those values change.

function showUsername() {
  if (status.isOnline && friend.username != '') return true;
}

This function must observe the properties it depends on (status.isOnline and friend.username). You can have a look at RxJS or other libraries for achieving this in a more "standard" way.



来源:https://stackoverflow.com/questions/61196788/how-to-deal-with-race-conditions-in-event-listeners-and-shared-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!