突然回忆起来之前跟同事们争论的一个问题,记录一下。

主要问题是,当页面中显示 xx 分钟,或 xx 小时,是由服务器处理还是客户端处理。

举个例子,我们有一个资源,比如帖子吧 posts,数据返回如下

1
2
3
4
5
6
7
8
{
"id": 1,
"user_id": 1,
"title": "标题",
"content": "内容",
"created_at": "2017-08-20 15:13:52",
"updated_at": "2017-08-20 15:13:52"
}

我们所有的接口,统一都会有 created_at 这个数据,格式统一为 yyyy-mm-dd HH:mm:ss

  • 接口在数据中,找个地方返回 "5 分钟前"
  • 客户端通过 created_at 按照自己的需求做格式化

哪一种解决方法更好呢

一系列问题及讨论

  • 服务器能把这个时间处理好,返回给客户端吗?

    我们完成一套接口,肯定是希望接口足够通用,我一点也不想考虑这个地方显示 “60 秒前” 还是 “1 分钟前”,鬼知道今天的设计稿和明天的设计稿还会不会是同一个样子。所以接口的通用性,应该体现在,我能满足任何设计稿,任何客户端的显示,但是当设计稿改变了,接口不会做乱七八糟的调整

    created_at 这种字段不可能改变,格式必须统一。

  • 能不能新加一个字段,返回 x 分钟前

    新加一个字段,比如我们叫 created_at_diff,那么接口看起来是这个样子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
    "id": 1,
    "user_id": 1,
    "title": "标题",
    "content": "内容",
    "created_at": "2017-08-20 15:13:52",
    "created_at_diff": "5 分钟前",
    "updated_at": "2017-08-20 15:13:52"
    }

    接口居然跟设计稿耦合了,接口需要根据产品的一些显示逻辑而改变。抛开设计稿,把这个接口说通,就是,这个接口除了提供完整的资源数据之外,还细心的告诉客户端,你可以这样显示数据。为了让客户端有更好的用户体验,接口也是操碎了心啊。这个接口既然操了这份心,其他的接口是不是也要多操心一下。

    那么为什么这个逻辑不能做到客户端里面去呢?谁家的接口会有这种东西啊?

  • ​客户端的本地时间可能不准,跟服务器时间做运算的时候可能有异常,所以建议服务器处理

    其实这是一个时间同步的问题,每一个 http 请求的 response 中其实都会有一个 Date 的 header。这个为了说明报文是什么时候创建的

    Date →Sat, 19 Aug 2017 16:09:39 GMT
    

    格式也是固定统一的,客户端可以根据这个来完成与创建时间的计算。
    或者这个时间差异可以放在最开始,app启动,用户登录,或者获取用户信息的时候,在全局存放时间差,这样也能供其他地方显示使用。

    再退一步,2017-08-20 15:13:52Sat, 19 Aug 2017 16:09:39 GMT 这样两个时间格式不统一啊,处理不方便,那么我们统一所有接口返回 X-SERVER-DATETIME → 2017-08-20 15:13:52 可好?

  • 客户端的运算会耗时,列表数据很多的时候,会卡顿,建议服务器处理

    这样的时间计算也会卡顿?这该如何来界定,找几个手机,5000次计算测试耗时?怎么都感觉这个计算量是不是太少了点…

  • 客户端其实哪怕有一丁点的性能损耗,其实都可以由服务器处理

    虽然不同意,但是 “额。。。”

  • 设计稿变动的时候,客户端的变动成本大,需要重新发布新版本,由服务器处理好了,客户端直接显示,这样变动的成本会低很多

    客户端显示成什么样,应该由自己控制,行间距啊,最多能显示多少个字,显示的美不美观等等。

    举个例子,如果现在是客户端直接拿接口数据字符串 “5 分钟前” 显示在某个位置,某一天,产品说,这样不好,显示出来完整的时间,于是服务器数据返回了 “2017年08月20日 15:13:52”,客户端显示不下了,产品说,试试把精确到分钟,于是服务器返回 “2017年08月20日 15:13”,好像可以了。

    这个例子感觉不应该存在,本来页面完全由客户端控制,变成了由服务器接口控制,是不是没有把各自该做的事情理清楚。页面变动就是应该客户端发版本,这样新旧版本之间都不会出现任何关系,也不会涉及到接口的改变。

    作为一个接口,不能稳定通用,整天跟着产品样式做变动,感觉好难受。

  • ios 或 android 做这样的数据处理会麻烦很多,服务端处理起来特别方便。

    逻辑其实都是一样的,根据当前时间与数据时间,做几个对比,有一些if else,只是用不同的语言去实现。不确定是否真的那么麻烦。

结果

考虑到,每个人的理解,说服大家的难度,工时,工期,人力成本,结果是接口增加了一个 created_at_diff 的字段。