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

了解下现在接口返回都是什么形式, 要不要提示文本?

  •  1
     
  •   onikage · 2021-07-26 10:39:02 +08:00 · 5779 次点击
    这是一个创建于 1214 天前的主题,其中的信息可能已经有所发展或是发生改变。

    http, json. 以登录接口为例, 两种方案:

    1. 返回{"code":0} 代表成功, {"code":1} 代表用户名密码不匹配. 前端页面自己根据 code 显示不同提示文案.
    2. 返回{"code":0,"msg":"登录成功"}, {"code":1, "msg":"用户名密码不匹配"}, 页面上直接显示 msg 属性的文本. 我个人认为第二种非常啰嗦, 一个 code 足以说明问题, 但是好像不少人都习惯第二种.
    77 条回复    2021-07-29 08:45:26 +08:00
    Bazingal
        1
    Bazingal  
       2021-07-26 10:42:25 +08:00
    第二种,前端不用写一堆枚举
    coolcoffee
        2
    coolcoffee  
       2021-07-26 10:46:39 +08:00
    同样是第二种,你封装好以后,自动将 code 对应的提示语带出来就好了。 这样能方便调试以及前端提示,同时也能根据特殊 code 单独处理逻辑。

    不然后端自己 postman 调试的时候,看到 code 还要有个查询或者去读记忆过程。
    nekoneko
        3
    nekoneko  
       2021-07-26 10:46:54 +08:00   ❤️ 1
    我现在要根据用户的预言返回 中文,拉丁文,英语,日语,繁体中文,阿拉伯语,法语,德语,韩文,俄语,西班牙语,葡萄牙语,印地语.你是要前端来搞嘛?今天我又要加一种语言呢?
    misaka19000
        4
    misaka19000  
       2021-07-26 10:50:11 +08:00
    第二种,方便排查问题
    sunjiayao
        5
    sunjiayao  
       2021-07-26 10:51:55 +08:00
    接口响应状态还是第二种好。
    一个 code 对应不同 msg 时,前端只需要阻断当前流程并 toast 提示即可。
    kop1989
        6
    kop1989  
       2021-07-26 10:52:55 +08:00
    如果是第一种的话,你怎么保证前端的 code 与后端的 code 语义一致呢?
    adnoh
        7
    adnoh  
       2021-07-26 10:53:49 +08:00 via Android
    我现在接口都用这种形式的了{"ok":true,"msg":"登录成功","data":{}}
    aogu555
        8
    aogu555  
       2021-07-26 10:55:38 +08:00
    第二种,如果第一种的话如果需要增加 code 类型,那么需要通知前端去修改 msg 映射,而且也要单独维护一份接口文档,但是第二种后端自己改就行了,减少不必要的沟通成本。
    onikage
        9
    onikage  
    OP
       2021-07-26 10:57:53 +08:00
    @nekoneko 增加一种语言难道前端不用改么? 第一种的话在增加语言时只需要前端发布新版本就好, 第二种新增语言前后端都得有工作量.
    onikage
        10
    onikage  
    OP
       2021-07-26 10:59:50 +08:00
    @Bazingal 你是前端吗? 这部分工作量无论前后端都得做. 我作为后端来说, 这部分想图省事扔到前端做.
    onikage
        11
    onikage  
    OP
       2021-07-26 11:00:20 +08:00
    @sunjiayao 一个 code 怎么对应不同 msg?
    onikage
        12
    onikage  
    OP
       2021-07-26 11:01:26 +08:00
    @aogu555 这个场景倒是很有道理.
    anzu
        13
    anzu  
       2021-07-26 11:04:41 +08:00
    当然是第一种,方便以后做 i18n,不用再通知后端用户切换了语言。至于前后端 code 一致性,如果懒得写文档,后端可以另写一个内部用的接口枚举所有 code 映射,前端请求一下即可。
    sunjiayao
        14
    sunjiayao  
       2021-07-26 11:04:53 +08:00
    @onikage 比如说定义 code 1 为错误 code 。msg 有可能是 用户名密码错误 验证码错误 验证码发送过于频繁 等等
    h1104350235
        15
    h1104350235  
       2021-07-26 11:15:58 +08:00
    第二种好
    onikage
        16
    onikage  
    OP
       2021-07-26 11:17:53 +08:00
    @anzu 对, 我也是这么想的. 但是目前公司内支持第二种的人比较多.
    onikage
        17
    onikage  
    OP
       2021-07-26 11:18:13 +08:00
    @h1104350235 好在哪里?
    onikage
        18
    onikage  
    OP
       2021-07-26 11:19:02 +08:00
    @sunjiayao 这样其实可以通过定义多个错误代码解决.
    onikage
        19
    onikage  
    OP
       2021-07-26 11:19:23 +08:00
    @kop1989 接口文档啊.
    sunjiayao
        20
    sunjiayao  
       2021-07-26 11:25:06 +08:00   ❤️ 1
    @onikage 其实一般来说,不需要执行特殊流程的异常返回是不需要单独定义 code 的。我的习惯是这样
    falcon05
        21
    falcon05  
       2021-07-26 11:30:15 +08:00 via iPhone   ❤️ 1
    第二种,方便自己调试。不写文档
    SoloCompany
        22
    SoloCompany  
       2021-07-26 11:32:06 +08:00
    i18n 已死请烧纸
    Kilerd
        23
    Kilerd  
       2021-07-26 11:41:14 +08:00   ❤️ 7
    第一种,但是会遵循第二种加一个 msg 不过是 enum 格式的
    例如:
    登录成功: {"code":0,"msg":"LOGIN_SUCCESS"}
    密码不对: {"code":1, "msg":"INVALID_PASSWORD"}

    这样前端可以用 msg 里面的 key 做 i18n

    别说 i18n 没用,问就是你做的项目不够国际化。
    gamexg
        24
    gamexg  
       2021-07-26 13:23:21 +08:00
    app 等本地应用,
    gamexg
        25
    gamexg  
       2021-07-26 13:26:47 +08:00
    @gamexg #24

    app 等本地应用,不建议第一种.
    app 发布时不可能预期到所有错误提示,后期绝对后出现变更.
    第一种没有了灵活性.
    wheeler
        26
    wheeler  
       2021-07-26 13:48:51 +08:00 via iPhone
    借楼问下,有了 code 之后 http 响应码是都返回 200 吗?
    Leonard
        27
    Leonard  
       2021-07-26 14:01:04 +08:00
    第二种,灵活一点,后台可以随意新增新的提示语
    whusnoopy
        28
    whusnoopy  
       2021-07-26 14:11:53 +08:00   ❤️ 1
    参与讨论

    先回答 #26 的问题:有了 code 以后 HTTP 响应码都返回 200 。原因一是因为 HTTP 码表示的是网络层的成功与否,而接口的很多错误并不是网络层的,二是即使是网络层的错误,比如 403 Forbidden,如果直接在 HTTP 响应码返回,可能会被更上层的框架拦截处理,压根到不了应用里来处理

    另外回楼主,为什么非得争论哪个好,不能一起用。实践中我这边一般返回的都是 `{"code": 1, "msg": "登录失败:用户不存在", "data": {}} ` 这样的,前端通过 0 和非 0 判断是否成功,对于非 0 的情况,可以根据 code 去自己组织异常处理和用户反馈(可能还用到 data 里的内容),也可以用我们自己框架层逻辑直接显示 msg 并退出调用

    一般最终的处理逻辑和标准都是以后端为准,哪怕后端实现错了那也才是真实情况,所以我写后端会连 code 带 msg 并附上 data 一起返回,前端爱怎么用随便他(虽然大多数时候是另一个我
    yolee599
        29
    yolee599  
       2021-07-26 14:27:59 +08:00
    @wheeler #26 返回 200 可以保证所有应用错误都能收到,应用错误用 http 响应可能被丢弃,到不了应用层。
    otakustay
        30
    otakustay  
       2021-07-26 14:36:54 +08:00
    你能不能保证你的 code 的 msg 永远是一对一的,如果可以就不需要 msg 了让前端做字典就行,做国际化也方便些
    但我从来没见过 code 和 msg 能一对一的时候,最糟糕的兜底错误怎么处理呢?
    masterclock
        31
    masterclock  
       2021-07-26 14:41:16 +08:00
    借楼,第二种,多语言化怎么解决的?前端请求的时候带着语言信息,服务之间传递下去,每个服务各自处理多语言?
    netwjx
        32
    netwjx  
       2021-07-26 14:46:29 +08:00
    1 和 2 的真实差异是?

    我猜的: 每次网络通讯, 1 比 2 快 1ms? 每次 debug, 2 比 1 快一小时?


    不涉及核心的比较(比如用"好" 来形容 )都是耍流氓
    nekoneko
        33
    nekoneko  
       2021-07-26 15:20:31 +08:00
    @adnoh #7 这种返回对 对接 不太友好,跟前端交互足够
    nekoneko
        34
    nekoneko  
       2021-07-26 15:21:22 +08:00
    @onikage #9 前端所有文本都由后端返回,前端只需要做好显示功能
    Hallelu
        35
    Hallelu  
       2021-07-26 15:32:44 +08:00
    第一种的话,能保证一对一,是最好的。但我对接的,还没见过一个 code 就是对应一个 msg 的,例如密码失败,用户已登录,这种情况,用第一种还得再去请求一下。
    aliveyang
        36
    aliveyang  
       2021-07-26 15:33:56 +08:00
    第二种,不要增加沟通成本
    Jooooooooo
        37
    Jooooooooo  
       2021-07-26 15:36:35 +08:00
    当然是第二种

    后端来维护各种文本远比前端要灵活
    lei2j
        38
    lei2j  
       2021-07-26 15:36:41 +08:00
    肯定第二种好,后端解决更好。
    akira
        39
    akira  
       2021-07-26 15:40:29 +08:00
    喜欢第二种,调试起来各种方便
    ccyu220
        40
    ccyu220  
       2021-07-26 15:43:04 +08:00   ❤️ 4
    肯定是第二种啊,前端在 header 中提交语言代码,后端根据语言返回不同的语言提示。
    makun123
        41
    makun123  
       2021-07-26 15:56:17 +08:00
    必须第二种好,使用起来也更灵活些,一个 code 可以对应多个 msg,我还有场景用到,一个 code 对应的 msg 提示中拼接一些业务处理后的提示参数,第二种直接返回了,第一种还得和 FE 特殊约定下
    makun123
        42
    makun123  
       2021-07-26 15:59:04 +08:00
    还有题外问下楼主已经 40+了么
    FallenTy
        43
    FallenTy  
       2021-07-26 15:59:07 +08:00
    第二种后端也能做国际化,功能实现都一样,这种就是少数服从多数了。
    KyrieJoshua
        44
    KyrieJoshua  
       2021-07-26 16:23:17 +08:00
    @onikage 10L
    如果抱着图省事的心态让前端做,以后前端就不理你了。。
    zgray
        45
    zgray  
       2021-07-26 16:42:19 +08:00
    有种场景必须用 2,而不能用 1 。

    当后端有个原来预想外的逻辑要额外增加错误提示,但是发布前端已经来不及(前端可能是 APP,或者是利用 electron 之类的客户端方案),必须后端先修复,这个时候前端如果是用 msg 提示,那么后端是可以立刻修复后发布。而不给 msg 只用 code,前端这时候只能报“内部错误”这样的提示了。
    ily433664
        46
    ily433664  
       2021-07-26 16:57:38 +08:00
    肯定是第二种,就算你想让前端自己控制提示语句,第二种也可以兼容
    queuey
        47
    queuey  
       2021-07-26 17:02:53 +08:00
    第一种很傻,
    code 是通用的,如果按照第一种来的话,付款失败可能有几十种原因,判断 code 给几十个 前端自己处理?
    Hslacker
        48
    Hslacker  
       2021-07-26 17:29:40 +08:00
    第二种,前端不用写一堆枚举
    ytmsdy
        49
    ytmsdy  
       2021-07-26 17:35:28 +08:00
    第二种吧!这样还能悄咪咪的加入一些其他的提示脚本,这样前端就不需要重新发布。
    要不然新增一个提示信息,前端需要修改,后端也需要修改。
    zxCoder
        50
    zxCoder  
       2021-07-26 17:38:13 +08:00
    第二种,只用修改一端
    aguesuka
        51
    aguesuka  
       2021-07-26 17:44:22 +08:00
    当然要, 后者是前者的超集, 第一种方案能实现的第二种都能实现. 第一种情况需要维护一个超级大的枚举, 非常反设计.
    balabalaguguji
        52
    balabalaguguji  
       2021-07-26 17:58:49 +08:00
    刚好有写一个响应参数的教程 https://easydoc.net/posts/response-data-design/
    libook
        53
    libook  
       2021-07-26 18:08:23 +08:00
    看需求。

    如果前端需要对文本进行风控或限制的话,第一种方案比较合适。
    如果希望能快速调整文本的话,第二种比较合适。
    liuhuihao
        54
    liuhuihao  
       2021-07-26 18:16:23 +08:00
    当然是第二种
    常见的场景就是 APP,产品可能要修改一个小小的错误文案,使用第一种的话,就要给所有用户推送更新才行,第二种后端直接修改即可。
    sytnishizuiai
        55
    sytnishizuiai  
       2021-07-26 18:25:24 +08:00
    我一开始想用 1,但是 msg 中文也写了,顺带的,后来慢慢变成 2 了,code 自己写多了烦,还要写文档,前端找,还不如用 2 的方式,我现在 code 也不写多了,除非需要前端去判断的才额外写个 code 。
    onikage
        56
    onikage  
    OP
       2021-07-26 18:39:19 +08:00
    @netwjx 作为后端, 我认为的核心就是少一部分工作量以及对应的 bug.
    onikage
        57
    onikage  
    OP
       2021-07-26 18:47:06 +08:00
    waytoshine
        58
    waytoshine  
       2021-07-26 19:05:51 +08:00 via iPhone
    你的观点,只能说你目前没做过什么稍微大点的系统的开发
    kekxv
        59
    kekxv  
       2021-07-26 19:54:35 +08:00 via iPhone
    前端:?要不要我把后端接口也做了?🐶
    onikage
        60
    onikage  
    OP
       2021-07-26 19:59:04 +08:00
    @waytoshine 什么叫大?
    makun123
        61
    makun123  
       2021-07-26 20:42:40 +08:00
    @onikage 对外提供服务的 api 肯定是要是要一个 code 对应一个 msg
    onikage
        62
    onikage  
    OP
       2021-07-26 20:43:40 +08:00
    @makun123 快了
    IvanLi127
        63
    IvanLi127  
       2021-07-26 21:03:55 +08:00 via Android
    非生产环境 具体的错误描述得给。在生产环境中,如果没有其他可选项的话,我选第二种。
    daimubai
        64
    daimubai  
       2021-07-26 22:05:00 +08:00
    肯定第二种,对于可变的东西后端做控制更好,毕竟产品总是需要改文案什么的,而且第二种前端调试起来也方便吧,至于国际化,如楼上所说,可以在请求头中传递 language,不过我想大多人的项目还用不到国际化
    Felldeadbird
        65
    Felldeadbird  
       2021-07-26 22:38:43 +08:00
    第二种。国际化解决方案很多啊。 后端判断,前端判断。两端一起判断。第二种可以直接定位到错误。

    第一种需要准确定制 code 码,后期维护成本高
    queuey
        66
    queuey  
       2021-07-26 22:59:39 +08:00
    @onikage 57 微信这种是提供 API 给到外部的啊,和自己做完全不是一个概念。你要是觉得 1 好那就用 1 呗。只要你们前端没意见
    xujinkai
        67
    xujinkai  
       2021-07-26 23:25:33 +08:00 via Android
    第二种方便调试,前端不一定用但不能没有
    gtanyin
        68
    gtanyin  
       2021-07-27 09:02:54 +08:00
    见过懒的后端,没见过你这么懒的。。
    xianxiaobo
        69
    xianxiaobo  
       2021-07-27 09:07:41 +08:00
    我前后端都自己写,我选择第二种,维护方便啊,要改 code 和 message 只要改后端代码就行了。不然后端代码加个 code,然后前端代码再去加 message?
    whusnoopy
        70
    whusnoopy  
       2021-07-27 09:14:54 +08:00
    @onikage 关于微信的返回码

    1. 人家给了全局返回码又不是不能再多带个 msg 和 data,多带 msg 和 data 并不影响你本来就有 code 返回和 code 全局唯一性,比如 code 是 -1 表示「系统忙,请稍后再试」,那到底是等一秒后重试还是一分钟后重试,这种就可以在 msg 和 data 里体现了

    2. 微信的开放平台也不是必然正确和唯一正确的做法,比如他们家授权过程还要带着 appid 和 secret 明文传这就很诡异 https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html,虽然有用 https,虽然可以设置 IP 白名单,对比下支付宝,都是公私钥签名验证 https://opendocs.alipay.com/support/01rave
    penll
        71
    penll  
       2021-07-27 09:41:15 +08:00
    微信的 code 要看具体情况。msg 是给用户的友好信息,code 是能定位到具体问题,难道你要告诉用户 xxx 参数不能为空这种情况吗?
    EmotionV
        72
    EmotionV  
       2021-07-27 10:06:48 +08:00
    明显第二种啊,要是 pm 说要改个提示,后台直接改下上线就行。app 啥的还要重新打包提交审核,麻烦的很。
    strongcoder
        73
    strongcoder  
       2021-07-27 10:11:52 +08:00
    {
    "status": "200",
    "msg": "OK",
    "isPC": 1,
    "isHome": 1,
    "data": {
    "status": "0",
    "data": "new"
    }
    }
    no1xsyzy
        74
    no1xsyzy  
       2021-07-27 11:21:37 +08:00
    type Response<T, F> = {code: "SUCCESS", data: T} | {code: F};

    例:
    {"code": "SUCCESS", data: {"token": "..."}}
    {"code": "BAD_LOGIN"}
    {"code": "UNKNOWN_ERROR"}
    {"code": "SERVER_DOWN"}

    说了多少次,不要用数字暧昧地表示状态,用 Symbol 去明确。那样后端调试也不需要查询或记忆 code
    成功就是成功不需要 msg,warning 不应当以 toast 形式提供。

    (有时返回 http code 444 以实现某些目的)

    评论,这问题甚至不值得辩论,因为最优选项显而易见:

    #23 差门前一脚,code 的存在毫无意义,enum msg 不就足以提供所有信息了吗?

    #25 所说的,应当采用单独的接口传递以实现关注点分离。

    #34 那为什么要返回 json,直接 html 返回整个网页解决所有问题。 —— 我确实有这么干的。

    #71 接口返回信息不应当用于定位问题,定位问题应当用后端 log,否则可能泄漏代码形态和逻辑。
    netwjx
        75
    netwjx  
       2021-07-27 12:40:21 +08:00
    @onikage 研发过程成本 和 运行时成本 比起来

    几乎可以忽略, 否则软件行业不会这么发达

    所以决策判断应以后者为主, 降低运行成本, 减少运行风险
    onikage
        76
    onikage  
    OP
       2021-07-28 10:54:47 +08:00
    @gtanyin 实际早年还写 jquery 那会因为前后端都是一个人, 所以就是这么搞的. 也没感觉增加多少工作量.
    gtanyin
        77
    gtanyin  
       2021-07-29 08:45:26 +08:00
    @onikage 好的,学习了~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   991 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:18 · PVG 04:18 · LAX 12:18 · JFK 15:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.