使用缓存和网络策略进行表单处理,如何处理这种情况



我正在为一个新的web应用程序使用urql和Svelte。

我遇到了一个逻辑问题,我不知道如何最好地解决。

假设我有很多todo,并且这些todo的列表已经缓存在我的手机浏览器上。

当我在地铁上(非常慢的网络(时,我打开一个来编辑它(然后应用程序从缓存加载带有todo的编辑表单(;CCD_ 1";在我妻子更改它之前不久,todo重新更新了自己,撤销了我在文本区写的所有更改。

你认为怎样才能解决这种情况?

  1. 我应该等待cache-and-network完成才能编辑表单吗?(这对于离线用户体验来说并不好(;

  2. 我应该警告用户有更新的todo吗?

  3. 我是否应该警告用户,只有当我将todo保存在后端的DB中时,才有更新的todo?

  4. 其他建议?

您可以使用navigator.onLine来检查您的用户是在线还是离线。如果他处于脱机状态,请将他的更改保存到localStorage。当状态再次改变时;您可以将当前状态与localStorage进行比较,并相应地更新表单。

我所说的大部分逻辑都在这里解释

如果您需要在localStorage中保存表单的帮助,可以使用以下模板:

[].forEach.call(document.querySelector('#form-id').elements, function(el) {
localStorage.setItem(el.name, el.value);
});
// then refresh the page and run this to restore your form values:
[].forEach.call(document.querySelector('#form-id').elements, function(el) {
el.value = localStorage.getItem(el.name);
});

您描述了一个经典的race condition,其中两个用户在同一资源上创建不同的操作(在我们的用例中是db中的记录(

简短回答:record versioning-为每条记录管理一个唯一的版本号。只有在使用相同版本值交付时才能执行更改

长答案:假设我们使用no-sql db,其中每个列表都保存在cache-and-network0集合中,其中每个记录看起来像这样:

{
id: 'uuid-4',
items: [
{ name: 'item #1', checked: false },
{ name: 'item #2', checked: true },
{ name: 'item #3', checked: false }
],
version: 1648727895753
}

在上面的示例中,我使用了timestamp作为记录版本(使用new Date().getTime()方法(。每次更新此记录时,版本也会发生变化。

现在,让我们再次描述您的场景:

2个用户从服务器下载相同的CCD_ 13。此时,两个用户都具有相同的版本值(比如版本A(。现在,让我们假设一个用户进行了更新,而另一个用户处于脱机状态(在您的示例中,由于旅行(。为了使这种模式发挥作用,我们在每次成功更新后都会更改版本值,这样现在记录就有了一个新的版本值(比如版本B(。当另一个用户尝试进行更改时,它将被阻止,因为他仍然使用旧版本号(在我们的示例A中(。为了进行更改-应首先下载最新版本(B(,然后用户将更新自己的编辑并将其更改写入数据库(此过程将产生C版本的更新记录(

因此,为了实现这一点,应该创建以下机制:

服务器端(数据库逻辑(

  • 记录更新
    • 只有当请求版本值等于记录版本值时才进行更新
  • 获取记录时
    • 返回当前版本值的记录

客户端(应用程序逻辑(

  • 应用程序加载
    • 获取当前待办事项列表记录(通过id字段(
  • 记录更新
    • 使用当前版本值向服务器发送更新
    • 如果更新失败:
      • 将当前待办事项列表记录保存为old version
      • 获取当前待办事项列表记录(通过id字段(
      • 合并更改(您将决定如何将其反映给用户(
      • 将更新发送到具有当前版本值的服务器(它现在是更新最多的一个(

技术说明

  • 两个记录版本之间的合并(例如,介于到基于JSON的对象之间(本身就是一个完整的宇宙。您可以使用第三方库来发现差异(例如json-diff(,或者决定应用默认行为(例如:如果在数据库中删除了列表中的项目,则会应用不同的样式,以便用户理解该项目已被删除(
  • 即使是现在,我们仍然有竞争条件的风险(嗯……在使用简单的todo list时极不可能,但在高负载的应用程序中可能会发生(。对于生产准备就绪的设置,请考虑使用消息队列,以便按特定顺序应用所有操作(先进先出(。再说一遍,这对你的用例来说是一种过度的处理,但由于我们在这里解决了一个更普遍的问题,我认为值得一提

相关内容

  • 没有找到相关文章

最新更新