【发布时间】:2021-05-26 21:59:46
【问题描述】:
我正在使用 Svelte 构建一些绑定到 Web 套接字的表单。如果用户更改了一个值,组件将发送一个 PUT 请求来更新数据,然后服务器会将更改广播给所有用户。但这让我陷入了一个奇怪的困境。
主页面如下所示:
<script>
import { UOM } from './channels'; // <-- A readable store of an array of objects.
import UOMEdit from './UOMEdit.svelte';
</script>
{#each $UOM as unit (unit.uomId)}
<UOMEdit uom="{unit}"/>
{/each}
而 UOMEdit 基本上是这样的:
<script>
export let uom;
let { uomId, name, standardUnitId, toStdUnitMultiplyer } = uom;
</script>
<!-- Various controls to manipulate the UOM's data -->
这对这个用户来说很好,但如果“uom”的值发生变化,它不会反映在控件中。换句话说,其他用户不会看到该用户所做的任何更改。于是我就尝试了这样的安排:
<script>
export let uom;
$: uomId = uom.uomId;
$: name = uom.name;
$: standardUnitId = uom.standardUnitId;
$: toStdUnitMultiplyer = uom.toStdUnitMultiplyer;
</script>
现在我遇到了相反的问题。我可以看到服务器广播的任何更改,但无法在本地进行任何更改。
我更喜欢将属性解构为变量的想法,因为它让一切变得如此简单。有没有办法知道 uom 的属性和局部变量的区别是因为 uom 发生了变化,而不是因为用户一直在修改本地副本?
【问题讨论】:
-
您可以在
onMount()中创建uom的副本,然后在afterUpdate()中将新的uom与该副本进行比较。如果不同,则说明更新来自服务器。 -
感谢您的回复。这似乎是我要去的地方。最近我浪费了很多时间来处理转换,结果发现 Svelte 已经为我解决了我的问题,但这里可能并非如此。我会更新我原来的问题。
-
如何解决竞态条件?例如。如果两个用户同时更改值,应该在表单中显示什么?
-
这是一个很好的问题,也引起了我的一些担忧。对于我的使用,更改是通过 PUT 请求进行的,并由 Web 套接字反映。所以目前在客户端,我说网络套接字总是赢。如果您更改了一个值并且更新来自具有匹配值的服务器,则丢弃本地用户的更改(因为它们匹配)。如果您正在更改值并且更新到达,请直接从用户下方更新表单,但告诉他们原因。这不是我的第一选择,但这是我能想到的最好主意。
-
我应该补充的另一件事。客户端套接字使用一个小的 RxJs 来消除来自服务器的消息大约半秒。这无疑有助于减少无意义的喋喋不休和间歇性变化,导致各种页面无缘无故地重新计算。