javascript - 如何处理事件监听器和共享状态中的竞争条件?

标签 javascript asynchronous event-handling race-condition event-listener

我有 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之后执行,但从事件发射器的 Angular 来看我没有这种保证。我需要以某种方式在我的代码中实现这一点。

现在我当然可以简单地从 friendData 监听器中删除 if (sharedState.isOnline) { 并让它运行它的过程。然后,我将在两个处理程序完成后运行一个函数,并在某种程度上协调共享状态依赖关系:

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

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

问题是这个协调函数知道这个特定的数据依赖性用例;因此不能非常通用。由于存在大量相互关联的数据依赖性,这似乎更难实现。例如,我已经在处理其他订阅和其他数据依赖性,并且我的协调功能变得相当庞大和复杂。

我的问题是:有更好的方法来建模吗?例如,如果我保证处理程序将按特定顺序运行,我就不会遇到此问题。

编辑:预期的行为是使用sharedState并呈现一个UI,我希望用户名仅在状态isOnline为true时显示。

最佳答案

从@Bergi在评论中的回答来看,我暗示的解决方案似乎是最适合这种情况的。只需让事件处理程序设置自己的独立状态,然后观察值的变化并根据您需要执行的操作编写适当的逻辑即可。例如我需要显示一个用户名;该函数不应该关心顺序或了解时间:它应该简单地检查 isOnline 状态是否为 true 以及是否存在用户名。然后,只要函数的每个依赖项发生变化,就可以使用可观察模式来调用该函数。在这种情况下,该函数依赖于 status.isOnlinefriend.username,因此只要这些值发生变化,它就会观察并重新执行。

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

此函数必须观察它所依赖的属性(status.isOnline 和friend.username)。您可以查看 RxJS 或其他库,以更“标准”的方式实现此目的。

关于javascript - 如何处理事件监听器和共享状态中的竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61196788/

相关文章:

javascript - 用js模拟悬停几个映射的圆形按钮

javascript - ExtJs4 如何在循环中创建动态函数

javascript - 如何将参数(事件除外)传递给事件处理程序?

C#:如何防止调用失败

javascript - 传递给 .click() 方法参数的参数是否始终是 Event 对象?

JavaScript:document.all.item() 替换

javascript - 使 CSS 菜单项和标题扩展到正确的宽度

javascript - 使用 `localStorage` 时,数组不会存储在 `callback` 中

python - 在异步任务之间自由切换的正确方法是什么?

c# - 如何在 Xamarin Android Activity 回调中使用等待