Как бороться с условиями гонки в событиях слушателей и общего состояния? - PullRequest
0 голосов
/ 14 апреля 2020

У меня есть 2 прослушивателя событий, которые работают с одними и теми же общими данными / состоянием. Например:

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;
  }
});

Моя проблема в том, что эти события генерируются в любом порядке. Событие friendData может наступить до friendStatus. Но friendData что-то делает с данными, возвращенными из friendStatus. Другими словами: мне нужен обработчик событий для friendData для выполнения после friendStatus, но у меня нет этой гарантии с точки зрения источника событий. Мне нужно как-то реализовать это в моем коде.

Теперь, конечно, я мог бы просто удалить if (sharedState.isOnline) { из прослушивателя friendData и позволить ему работать. Затем я бы запустил функцию после завершения обоих обработчиков и несколько согласовал бы зависимости общего состояния:

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

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

Проблема в том, что эта функция согласования знает об этом конкретном c случае использования зависимостей данных; следовательно, не может быть очень обобщенным c. С большими взаимосвязанными зависимостями данных это кажется намного труднее достичь. Например, я уже имею дело с другими подписками и другими зависимостями данных, и моя функция сверки становится довольно большой и сложной.

Мой вопрос: есть ли лучший способ смоделировать это? Например, если бы у меня была уверенность, что обработчики будут работать в определенном порядке c, у меня не было бы этой проблемы.

EDIT : ожидаемое поведение - использовать sharedState и рендеринг пользовательский интерфейс, в котором я хочу, чтобы имя пользователя отображалось ТОЛЬКО, если статус isOnline равен true.

1 Ответ

1 голос
/ 14 апреля 2020

Из ответа @ Bergi в комментариях решение, на которое я намекал, кажется наиболее подходящим для такого случая. Просто дайте обработчикам событий установить свое собственное независимое состояние, затем наблюдайте за изменением значений и запишите соответствующие логики c в зависимости от того, что вам нужно сделать. Например, мне нужно показать имя пользователя; эта функция не должна заботиться о порядке или иметь какое-либо представление о времени: она должна просто проверять, является ли статус isOnline истинным и есть ли имя пользователя. Затем наблюдаемый шаблон может использоваться для вызова этой функции всякий раз, когда меняется каждая зависимость функции. В этом случае функция зависит от status.isOnline и friend.username, поэтому она будет наблюдать и повторять выполнение при каждом изменении этих значений.

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

Эта функция должна observe свойства, от которых она зависит (состояние. isOnline и friend.username). Вы можете взглянуть на Rx JS или другие библиотеки, чтобы добиться этого более «стандартным» способом.

...