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

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

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

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

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

    按正常逻辑怎么来的脏数据呢? 不妨前端优化下前端逻辑避免脏数据. 后端严卡数据进入.
    yanz123
        19
    yanz123  
    OP
       110 天前
    全部粗暴丢弃的话有一个弊端,就是可能不是数据脏了导致前端没有把数据发给后端,可能是后端挂了导致的,这样后端再重启后,前端其实是可以把这些数据传到后端的
    darkengine
        21
    darkengine  
       110 天前
    @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  
       110 天前
    浏览器有自带的 indexDB 数据库
    yaphets666
        23
    yaphets666  
       110 天前
    17 楼说的应该没问题,调接口之前,清空 localStorage 相关字段,调接口后如果失败了,再把数据存回去。
    ccagml
        24
    ccagml  
       110 天前 via Android
    一定需要 20 条才能发?
    如果错了就把 20 分成 10,10 两组发,其中有错了在把 10 分成 5,5 发呢
    如果脏数据返回 400+
    后端挂了应该会返回 500+
    nekochyan
        25
    nekochyan  
       110 天前
    如果有脏数据为什么后端不把脏数据是哪些返回给前端,这样前端清掉这些脏数据不就行了吗
    a13761839322
        26
    a13761839322  
       110 天前
    数据错误是什么原因?代码原因还是业务原因,代码原因保证自己的健壮即可,业务原因就返回对应错误 ,修正数据(剔除错误条目)后 retry

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

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

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

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

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