V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iam
V2EX  ›  程序员

关于列表数据删除时前端展示那些事

  •  2
     
  •   iam · 2022-09-16 00:41:05 +08:00 · 1721 次点击
    这是一个创建于 781 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天下午,办公室的民工都在热火朝天的堆代码。突然前端的同志说,删除列表中的一些数据时会造成数据丢失或者重复,我有没有什么看法。作为一个资深不务正业的后端,我决定加入了这场讨论。

    交代一下背景:用户个人中心的任务列表需要做批量删除,因为做了分页,根据 limit (page - 1) * page_size, page_size 确实会出现这样的问题。

    数据举例:
    page1:00 01 02 03 04 05 06 07 08 09
    page2:10 11 12 13 14 15 16 17 18 19
    page3:20 21 22 23 24 25 26 27 28 29
    page4:30 31 32 33 34 35 36 37 38 39
    page5:40 41 42 43 44 45 46 47 48 49
    

    基于这样的背景我们 3 个人(分别称 A 、C 、D (本人),因为感觉小 B 不是很礼貌)提出了几种解决方案:

    1 )做标记

    C:或许把删除先做成标记,等到用户退出列表页或者回到个人中心的时候再提交删除.
    A & D:这样好像不太稳定,如果用户非正常退出的话不是很好正常提交,造成数据删除失败的现象,而且如果删除失败也不是很好的反馈给用户

    总结:NO

    2 )删除部分

    D:把删除数据最上页的数据更新,下面的全删除掉呢 例:删除 11 22 23 30 这些数据的话,就重新加载 page2 ,page3 、4 、5 全都删掉。数据变为

    page1:00 01 02 03 04 05 06 07 08 09
    page2:10    12 13 14 15 16 17 18 19 20
    

    A & C:这样用户体检不是很好,最好能定位到用户访问数据的最后一项

    总结:不适合批量删除,但是单项删除的话好像是可以的,因为删除页就是所在页?

    3 )补齐方式

    D:那删除之后,把最后一页做成补齐页记录误差,重新请求最后一页,创建一个新的页放进去呢 例:删除 11 22 23 30 这些数据的话,就把 page5 的前 4 个保留,删除掉后面 6 个,然后重新请求 page5 ,保存在 page6 ,记录误差为 1 ,数据变为

    page1:00 01 02 03 04 05 06 07 08 09
    page2:10    12 13 14 15 16 17 18 19
    page3:20 21       24 25 26 27 28 29
    page4:   31 32 33 34 35 36 37 38 39
    page5:40 41 42 43
    page6: 44 45 46 47 48 49 50 51 52 53
    

    此时的 page6 的数据为 page5 的数据,page1 + ... + page5 是前 4 页的总和,误差记录为 1 ,请求时页码加上误差即可
    A & C:这样会有点问题,如果删除的数据包括 page5 中的数据,那么补齐的数据需要去掉这些数据,如果删除的数据超过了一页,就需要计算最后几页,会比较麻烦

    总结:可以实现,但是较复杂

    4 )重新整合

    A:基于 3 的方法,在删除完成后把页码重新整合,再请求最后一页的数据,数据变为

    page1:00 01 02 03 04 05 06 07 08 09
    page2:10    12 13 14 15 16 17 18 19 20
    page3:   21       24 25 26 27 28 29 31 32 33
    page4:            34 35 36 37 38 39 40 41 42 43
    page5: 44 45 46 47 48 49 50 51 52 53
    

    总结:可以实现,但是数据量较大时可能会渲染卡顿?

    5 )请求时添加偏移量

    C:可以请求的时候,加上 delete____count ,数据查询时变为 limit (page - 1) * page_size - delete_count, page_size

    总结:可以实现,需要前后端的代码都做一下改动,可能因为数据源的程序不太好改动,那边的同事说实现不了 - -#

    写在后面

    1.以上讨论都是建立用户操作自己的列表时所做的操作,而且没有考虑到多端登录的问题;
    2.如果是在后台管理删除掉数据的话,用户的列表也会出问题,可能需要做缓存或者用别的方式通知用户?
    3.想起之前做的竞价功能,需要最新的出价在上面,然后做分页,列表的数据也会用这种问题,如果加上请求时间就可以解决,如果有需要的同志可以这样实现。
    
    好像还有很多的问题没有解决,但是今天有点晚了,就先这样。
    第一次写这种主题,抛砖引玉,如果大家有什么好的解决方法欢迎一起讨论哈
    
    14 条回复    2022-09-16 09:58:02 +08:00
    baiyun
        1
    baiyun  
       2022-09-16 00:51:42 +08:00 via iPhone
    为什么删除数据会造成丢失或者重复显示?
    baiyun
        2
    baiyun  
       2022-09-16 00:54:35 +08:00 via iPhone
    参考 ProTable 。前端处理基本都是固定的两种模式
    renmu
        3
    renmu  
       2022-09-16 01:00:11 +08:00 via Android
    按我的理解是 你们页面是无限滚动,然后删除之后导致分页出现问题了
    akira
        4
    akira  
       2022-09-16 01:00:23 +08:00
    参考 gmail 批量删除时候的实现方案。要么就是基于当前页的手动选择,要么就是基于规则的选择,且规则选择会有上限。
    edis0n0
        5
    edis0n0  
       2022-09-16 01:05:42 +08:00
    我们这边的处理方案是任何场景下删除都只是隐藏,API 会返回已经删除的数据只是前端不显示给用户,然后弄个计划任务每天凌晨 4 点彻底删除 200 天前标记删除的内容。
    Pastsong
        6
    Pastsong  
       2022-09-16 01:11:57 +08:00
    不要传 page ,传 offset
    CEBBCAT
        7
    CEBBCAT  
       2022-09-16 01:17:01 +08:00
    需要清晰阐述一下业务模型。为什么会数据丢失或重复?每个条目的排序 ID 是不是都是单调递增的?

    我猜楼主是瀑布流式列表?感觉产品太菜或者弱势。这种情况应该先决定能够接受的交互模型再设计实现方案。假如批量删除的条目直接抽空的话,页面会大幅度变化,用户还能记得刚才看到哪里吗?
    Building
        8
    Building  
       2022-09-16 06:57:02 +08:00 via iPhone
    前端数据和后端数据为什么非要耦合在一起? 前端取数据的时候应该用 cursor + offset
    iam
        9
    iam  
    OP
       2022-09-16 08:21:46 +08:00
    统一回复一下对 “删除数据会造成丢失或者重复显示” 的疑问,哈哈,可能描述的不是很清晰。
    前端请求数据的时候会传 page 和 page_size ,然后后端根据这个去查询。
    SQL:select *** from *** where *** limit (page - 1) * page_size, page_size;

    假如还是这些数据的话,在 page1 删除 00 ,那么前两页的数据就会变成
    page1:01 02 03 04 05 06 07 08 09 10
    page2:11 12 13 14 15 16 17 18 19 20

    原 page1:00 01 02 03 04 05 06 07 08 09

    因为已经渲染过,不做处理的话,就会造成 10 这条数据丢失。
    如果是用户删除的,大家说的这些方式好像都可以解决,但是后台删除数据的话,还是会有这样的问题。
    昨晚躺在床上想:在查询数据的时候需要传参开始访问时间,在这个时间之后删除的数据统计一下做一个偏移。
    例:
    load_start_time = 2022 09 16 00:00:00;(请求参数)
    delete_count = select count(***) from *** where delete_time > load_start_time
    不管是 offset 还是 page * page_szie , 游标都要向左偏移这个时间之后删除的数据条数 offset - delete_count
    xuanbg
        10
    xuanbg  
       2022-09-16 08:40:19 +08:00
    无限滚动的数据按时间倒序分页的话,确实存在一个几乎无法解决的问题。就是数据发生变化后加载下一页数据,要么重复(添加数据,把最后一条数据挤到下一页了),要么丢数据(删除数据,下一条数据顶到上一页去了)。传 offset 也仅仅能解决只有一个用户在操作的情况,别人给你干掉一条数据,你的 offset 是不会变的。
    唯一有效的办法是传当前页的最后一条数据的 id ,这要求 id 是自增或雪花 id 这种单调增长的。别无他法。
    Moeyua
        11
    Moeyua  
       2022-09-16 09:44:13 +08:00
    在页面加载时前端就「一次性」把数据全部获取下来,这里的「一次性」并不一定是一次请求,可以是多次请求,但重点是你要在用户删除数据前「主动」把所有数据加载完毕。之后前端自己做分页。
    这种方法的缺陷就是不适用于非常大的数据量,而且无法感知到后台删除的数据。但话又说回来,如果后台删了一条用户已经渲染过的数据,这种情况真的是无解,处理起来相当复杂。
    Moeyua
        12
    Moeyua  
       2022-09-16 09:49:36 +08:00
    正好之前处理类似问题时候画过一个图,给不清楚的人解释下为什么会丢数据
    zhyl
        13
    zhyl  
       2022-09-16 09:55:41 +08:00
    介绍一下我的做法:前端表格列表同时只显示一页的数据,触发删除行为时,先在后端删除,然后前端手动移除这一项,如果这一页的数据都被移除了,重新请求接口拉取新的数据
    zhyl
        14
    zhyl  
       2022-09-16 09:58:02 +08:00
    @zhyl 总结就是尽量少的在删除时重新请求后端拉取数据
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3072 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 13:39 · PVG 21:39 · LAX 05:39 · JFK 08:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.