V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
yanz123
V2EX  ›  程序员

请教一个前端暂存数据的问题

  •  
  •   yanz123 · 2023-02-10 17:27:36 +08:00 · 3243 次点击
    这是一个创建于 684 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我们有个功能会在前端记录客服的行为,积累了 5 分钟或者积累了 20 条记录就会调接口统一发到后端处理。
    如果后端接口报错了,前端就会把这些记录继续暂存在前端,等接口恢复之后统一发给后端。
    这种模式下前端可能会无限积累数据。
    比较极端的情况是 前端把数据暂存在 localstorage 里面,localstorage 被修改后会有脏数据,这样前端把脏数据发到后端会报 4XX 错误,导致前端永远无法再调通后端接口,除非把 localstorage 清空。
    不知道还有没有常见的情况会导致这种无法恢复的场景发生。
    这种情况下通常应该怎么设计?
    1.前端积累到一定的数据量之后,进入另一个逻辑,比如 100 条就分 5 段发送,有一段不成功就丢弃那段的所有数据?
    2.不知道有没有更好的方法。
    53 条回复    2023-02-12 14:54:39 +08:00
    0x19921213
        1
    0x19921213  
       2023-02-10 17:30:28 +08:00
    > 比较极端的情况是 前端把数据暂存在 localstorage 里面,localstorage 被修改后会有脏数据,这样前端把脏数据发到后端会报 4XX 错误,导致前端永远无法再调通后端接口,除非把 localstorage 清空。
    这个是什么意思。
    Chad0000
        2
    Chad0000  
       2023-02-10 17:30:51 +08:00 via iPhone
    浏览器的数据库中?
    yanz123
        3
    yanz123  
    OP
       2023-02-10 17:32:13 +08:00
    现在测试发现前端如果参数传错了的话,后端会返回 4XX 。 前端的数据是存在 localstorage 里面作为参数,如果参数被修改了,也会导致后端一直返回 4XX 。这样程序还没走到后端就失败了
    zoharSoul
        4
    zoharSoul  
       2023-02-10 17:37:20 +08:00
    sqlite 不行吗? 我看客户端都是存这个里 一般
    7911364440
        5
    7911364440  
       2023-02-10 17:38:31 +08:00
    cookie ?
    renmu
        6
    renmu  
       2023-02-10 17:41:18 +08:00 via Android
    你们的接口是经常会挂吗?加个最大重试次数呗
    renmu
        7
    renmu  
       2023-02-10 17:42:03 +08:00 via Android
    或者后端自己把脏数据洗了
    yanz123
        8
    yanz123  
    OP
       2023-02-10 17:42:26 +08:00
    问题的根本在于 前端如果有脏数据了之后前端自己感知不到,只会再次往后端发数据,后端返回 4XX 后,前端发送不成功 继续累积数据。
    darkengine
        9
    darkengine  
       2023-02-10 17:43:04 +08:00
    @zoharSoul sqlite 在 iOS/Android 上用,OP 问的应该是 web 的方案。

    可以跟后端协商一个脏数据的 4xx error code 啊,尝试上传的时候返回这个 code 就清掉 localStorage 的数据。
    Freakr
        10
    Freakr  
       2023-02-10 17:43:36 +08:00
    后端一律返回 200 ,解析不了的放另一个表里
    stillsilly
        11
    stillsilly  
       2023-02-10 17:44:08 +08:00
    @yanz123
    数据格式错误定一个单独的错误码,如果是这个错误码,把 localstorage 里的数据全部清除
    yanz123
        12
    yanz123  
    OP
       2023-02-10 17:44:19 +08:00
    接口并不会挂,今天测试的时候偶然发现,接口传错数据了会造成前端数据累积,引发的这个联想。
    4XX 的时候,逻辑并没有进到后端,后端无法处理。
    Chad0000
        13
    Chad0000  
       2023-02-10 17:45:59 +08:00 via iPhone
    @darkengine 浏览器也就是 web 有数据库。
    implion
        14
    implion  
       2023-02-10 17:46:16 +08:00
    不能在发送给服务器之前,从 localStorage 取出数据,然后校验下数据,再上传吗?你无法区分数据是不是脏数据?一般被服务器认为是脏数据,要么是数据格式不对,要么是时间戳不对
    darkengine
        15
    darkengine  
       2023-02-10 17:47:23 +08:00
    @Chad0000 有关键字没,我也学下,我们的产品是全部怼到 localStorage 了。
    implion
        16
    implion  
       2023-02-10 17:48:02 +08:00
    应该不是逻辑没进入后端,是后端用了数据格式校验的框架,在数据格式校验的时候就不通过,就给 throw 了
    hqmJoker
        17
    hqmJoker  
       2023-02-10 17:48:52 +08:00
    这不是调用完就清数据就行?(不管成不成功)

    因为如果本来数据有问题,还保存的话下次也会有问题。如果没有问题,那么这批数据就没用了,所以都得清掉,除非后端能返回更多的信息,根据返回信息清理旧数据。
    llsquaer
        18
    llsquaer  
       2023-02-10 17:51:28 +08:00
    后端数据错误或者不合理 返回 4xx 本来就合理

    按正常逻辑怎么来的脏数据呢? 不妨前端优化下前端逻辑避免脏数据. 后端严卡数据进入.
    yanz123
        19
    yanz123  
    OP
       2023-02-10 17:52:02 +08:00
    全部粗暴丢弃的话有一个弊端,就是可能不是数据脏了导致前端没有把数据发给后端,可能是后端挂了导致的,这样后端再重启后,前端其实是可以把这些数据传到后端的
    dingjs
        20
    dingjs  
       2023-02-10 17:53:23 +08:00
    darkengine
        21
    darkengine  
       2023-02-10 17:54:04 +08:00
    @dingjs
    @Chad0000

    嗯,通过某 AI 查到了这些:

    Client-side databases: There are several client-side databases that can be used in front-end development, including IndexedDB, WebSQL, and SQLite. These databases allow you to store and retrieve data on the client-side, and can be used in offline applications.
    LavaC
        22
    LavaC  
       2023-02-10 17:55:14 +08:00
    浏览器有自带的 indexDB 数据库
    yaphets666
        23
    yaphets666  
       2023-02-10 17:56:05 +08:00
    17 楼说的应该没问题,调接口之前,清空 localStorage 相关字段,调接口后如果失败了,再把数据存回去。
    ccagml
        24
    ccagml  
       2023-02-10 17:56:18 +08:00 via Android
    一定需要 20 条才能发?
    如果错了就把 20 分成 10,10 两组发,其中有错了在把 10 分成 5,5 发呢
    如果脏数据返回 400+
    后端挂了应该会返回 500+
    nekochyan
        25
    nekochyan  
       2023-02-10 18:05:28 +08:00
    如果有脏数据为什么后端不把脏数据是哪些返回给前端,这样前端清掉这些脏数据不就行了吗
    a13761839322
        26
    a13761839322  
       2023-02-10 18:05:41 +08:00
    数据错误是什么原因?代码原因还是业务原因,代码原因保证自己的健壮即可,业务原因就返回对应错误 ,修正数据(剔除错误条目)后 retry

    使用 localstorage 出于什么考虑,多 tab 的共享吗?简单点可以直接放内存,内存也没你想的那么脆弱,还方便管理
    darkengine
        27
    darkengine  
       2023-02-10 18:07:19 +08:00
    @a13761839322 估计有些埋点数据吧,放内存里关掉 tab 就没了。
    xwayway
        28
    xwayway  
       2023-02-10 18:08:07 +08:00 via iPhone
    或许这些数据并不重要,重要就不会采取这种方式来传输了,既然不重要,默认允许可以失败,即脏数据可以丢弃
    yanz123
        29
    yanz123  
    OP
       2023-02-10 18:08:49 +08:00
    是的 我们有埋点数据 关掉浏览器后数据还得在
    tool2d
        30
    tool2d  
       2023-02-10 18:12:24 +08:00
    用 indexdb 很合适,就是 API 是异步,而 localstorage 是同步,需要改改代码。
    libook
        31
    libook  
       2023-02-10 18:26:11 +08:00
    后端区分一下故障类型,前端根据后端返回的故障类型来选择策略:

    数据格式错误,清除 localstorage ;
    其他错误,稍后重试。
    seth19960929
        32
    seth19960929  
       2023-02-10 18:26:52 +08:00
    参考别家的系统看看. 用 localstorage 模拟队列.
    1. 0~100 先从 队列取到 0~20, 发送成功再删除队头 20 条, 发送失败放到队尾.
    2. 限制最大条数, 比如 1W 条, 超过之后老的删除掉.(取决于你的业务是否能删除)
    3. 让你们服务端应该不要返回错误, 永远存储数据, 后端自己做数据清洗
    gam2046
        33
    gam2046  
       2023-02-10 18:27:07 +08:00
    @yanz123 #19 就是#17 说的。后端返回 4xx 状态码就是数据本身的问题,无脑删掉就行了,留着,下次请求也是失败。如果是服务端挂了,返回的是 5xx 状态,或者直接是请求不通,那就留着下次再用呀。
    otakustay
        34
    otakustay  
       2023-02-10 18:53:07 +08:00
    前端也做个 FIFO 队列呗,实在不行了该丢就丢
    DrakeXiang
        35
    DrakeXiang  
       2023-02-10 19:02:05 +08:00
    记录行为那就是日志,日志怎么会需要修改和校验?如果后端给不出哪调出错那就只能如楼上所说,要么自己把出错的试出来去掉,要么就整块丢掉,大小自己掌握
    duan602728596
        36
    duan602728596  
       2023-02-10 19:03:29 +08:00
    IndexedDB 啊,前端也是有数据库的。
    localstorage 同步,还是存的字符串。不适合这个业务场景。
    每条数据可以对应唯一 ID ,重复的数据传到后端也不处理。
    KisekiRemi
        37
    KisekiRemi  
       2023-02-10 19:07:08 +08:00
    indexDB 啊,定 key 判断,或者加入时间区间,在某个时间区间报错就设定规则删除,具体逻辑看具体需求设置
    wonderl17
        38
    wonderl17  
       2023-02-10 19:11:58 +08:00
    前端校验数据就行了呀,后端那边也可以校验后丢弃不报 4xx 呀
    chairuosen
        39
    chairuosen  
       2023-02-10 19:14:36 +08:00
    让后端改
    Bijiabo
        40
    Bijiabo  
       2023-02-10 19:54:41 +08:00
    看起来这个设计有些问题。如果后端一直报错,或者后端用于接收错误的接口有一定概率报错,就比较崩溃了。

    如果我来做这个选择,我可能会考虑区别于当前的后端服务,使用一个单独的服务来收集数据。一些用户行为打点的服务,也有错误收集功能。
    a13761839322
        41
    a13761839322  
       2023-02-10 19:57:46 +08:00
    @yanz123 埋点感觉也没必要这种 积累上传...直接 img ping 的形式上报就行了
    不行就是 indexDB + rxjs 定时 observable 和数量 合并,还可以用 web worker 不影响主线程(不过这样有点过度设计,大多数产品也没多大并发,直接一次次往后台扔得了
    Finnn
        42
    Finnn  
       2023-02-10 21:08:14 +08:00
    Google analysis 的数据就是比较智能上报的, 数据出问题不能靠前端, 数据都到后台了后端也不处理的吗
    Finnn
        43
    Finnn  
       2023-02-10 21:09:11 +08:00
    @Bijiabo 用来接收日志的功能接口就不应该返回给前端错误, 没有这样做的
    adoal
        44
    adoal  
       2023-02-10 21:24:35 +08:00
    后端返回 4 了前端还“自己感知不到”?正常设计里难道 4 不是表示后端正常、前端传的数据有问题?“如果后端接口报错了,前端就会把这些记录继续暂存在前端”,难道你们的设计是后端接口返回任何非 2/3 的代码前端都当成是后端出问题了?
    darlinghsu
        45
    darlinghsu  
       2023-02-10 21:25:57 +08:00
    我们是统一收集发送,后端去存储,至于脏数据的问题自然有数据团队去做清洗和处理(也会和我们确认,写清理规则的时候

    如果明确错误数据需要改进的,就再反馈回来 优化埋点。
    wellerman
        46
    wellerman  
       2023-02-10 22:15:03 +08:00
    都 4XX 了,不就是前端问题了吗。后端再返回具体的错误码,前端根据具体的错误码去处理数据不就行了。
    joesonw
        47
    joesonw  
       2023-02-10 22:41:32 +08:00 via iPhone
    4xx 丢弃,5xx 才保存呗。
    ArcherD
        48
    ArcherD  
       2023-02-10 22:55:25 +08:00
    用 graphql 和 relay 的话框架里面对于这些问题都覆盖了 参见 Fetch Policies ,Error States with ErrorBoundaries
    后台不用 graphql 的话 就另说
    litchinn
        49
    litchinn  
       2023-02-11 09:35:33 +08:00
    @darkengine 现在有 wasm ,浏览器都可以跑 postgresql
    gausszhou
        50
    gausszhou  
       2023-02-11 19:15:08 +08:00
    让后端改成只要接收到埋点数据就返回 200
    gausszhou
        51
    gausszhou  
       2023-02-11 19:18:35 +08:00
    另外无限积累数据可不行
    1. 存储空间有限,localStorage 上限为 5MB
    2. 随着数据变多,localStorage 读写和 JSON 序列化 会占用较多的 CPU 时间,影响用户网页的正常业务和性能指标。
    paopjian
        52
    paopjian  
       2023-02-11 21:48:10 +08:00
    sqlite 现在支持 wasm,其实没必要累计记录数据吧,重要数据肯定 post 发了,不重要的日志扔给 mq 管他到底收没收到
    MMMMMMMMMMMMMMMM
        53
    MMMMMMMMMMMMMMMM  
       2023-02-12 14:54:39 +08:00
    看起来客服平台应该是第三方的了
    建议开个 ws ,这边发一条,直接同步发送到这个 ws 里去

    如果担心后端 IO 压力的话,可以在后端处理接到多少条推送之后再统一插入数据库
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1787 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 16:31 · PVG 00:31 · LAX 08:31 · JFK 11:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.