前端要以服务器的时间为准,有啥好用的库吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
vinsony
V2EX    Javascript

前端要以服务器的时间为准,有啥好用的库吗?

  •  1
     
  •   vinsony 2021-03-24 12:10:48 +08:00 8828 次点击
    这是一个创建于 1712 天前的主题,其中的信息可能已经有所发展或是发生改变。

    场景是大量客户端电脑时间都不准,也没有时间同步,只能在程序里请求后端时间接口获取真实时间。

    现在想法是程序只取一次服务器时间,然后在客户端模拟一个时间出来,关键要能支持 new Date 获取这个模拟时间,而且这个模拟时间能一直自动继续走。

    这样的需求有啥好用的库吗?

    46 条回复    2021-03-28 11:40:09 +08:00
    lasuar
        1
    lasuar  
       2021-03-24 12:13:46 +08:00
    前端会 像服务器一样时刻运行着?
    zvcs
        2
    zvcs  
       2021-03-24 12:14:45 +08:00 via iPhone   2
    加个 https 。如果他们时间不准就用不了
    vinsony
        3
    vinsony  
    OP
       2021-03-24 12:15:14 +08:00
    我意思是程序运行的时候从服务器取一次时间
    zhfapiu
        4
    zhfapiu  
       2021-03-24 12:16:48 +08:00
    计算服务端与客户端时间戳的差值,保存在前端
    MakeItGreat
        5
    MakeItGreat  
       2021-03-24 12:17:53 +08:00 via Android   1
    如果客户端的时间和服务器是有差值但是差值不变
    那么根据两者固定的差值计算
    jinsongzhao
        6
    jinsongzhao  
       2021-03-24 12:20:45 +08:00
    没有什么库,因为需要由服务端配合, 你的服务端可以是 java 的,c#的,或者时间服务等等. 而客户端如果直接修改电脑时钟,又需要权限. 其实思路也非常简单, 自己实现好了. 服务端返回时间, 客户端本地时间和服务端时间做一个差值, 然后显示时间时,始终加上这个差值. 也不用什么定时同步, 客户端不会连续工作几十天,也不会几个小时就跑出几秒的误差
    shenyuzhi
        7
    shenyuzhi  
       2021-03-24 12:23:31 +08:00
    window.Date = function() {...}
    opp
        8
    opp  
       2021-03-24 12:44:24 +08:00 via Android   1
    轮询吧,一次差值不靠谱。因为本机时间除了用户修改外,本身也会跳变,具体可搜下闹钟失效之类的案例。
    simple2025
        9
    simple2025  
       2021-03-24 12:47:29 +08:00
    每次 api,都把服务器时间返回回去?
    这个问题我也遇到过
    ligolas
        10
    ligolas  
       2021-03-24 12:53:00 +08:00
    response header 里面默认就带有服务器时间的,Date 字段,但是因为 CORS 的原因,你默认读不到,可以在服务器端配置一下 cors 头,你就可以读到了,这个时间再加上通信的时间,就比较准确了
    seki
        11
    seki  
       2021-03-24 12:54:36 +08:00   1
    实现个 ntp 算法
    zhuweiyou
        12
    zhuweiyou  
       2021-03-24 13:21:20 +08:00
    进来的时候 请求后端拿到服务器时间, 然后本地也 new Date, 做差值,

    是有误差 但是差值是不变的.

    后续只要 new Date + 差值 即可
    fumichael
        13
    fumichael  
       2021-03-24 13:59:06 +08:00
    #10 response header +1
    66beta
        14
    66beta  
       2021-03-24 14:02:37 +08:00
    讲真,大部分项目 http 请求都是封装好的,拿不到 header
    存差值比较合理
    tiedan
        15
    tiedan  
       2021-03-24 14:05:49 +08:00
    所有接口加个默认字段也行
    zhs227
        16
    zhs227  
       2021-03-24 14:34:46 +08:00
    存差值,多次按远近加权平均。
    hailun3202475
        17
    hailun3202475  
       2021-03-24 16:46:11 +08:00
    我们之前的方案是 websocket 走心跳,假如每五秒一次心跳,每次心跳服务端都返回服务端时间,前端拿到时间做每次校验修正,前端时间也时刻在走
    Hoshinokozo
        18
    Hoshinokozo  
       2021-03-24 16:49:17 +08:00
    @ligolas 通信的时间要怎么拿到呢?
    jmk92
        19
    jmk92  
       2021-03-24 18:32:15 +08:00
    据我了解,一些用户机器的时间不准,即使同步了时间,可能还是过一天差一点,过不几天又不准了。
    这个要牵扯到 CPU 时钟之类的,连他的机器都无法准确计算时间,你通过 js 算法 sleep 计算时间只会更不准。
    所以只有跟服务器通信才是王道,websocket 是最优解,轮训对服务器压力大,也可以通过 10-30 秒一轮询,计算一下和本机的差值,时间等于差值+他的本地时间。
    geekvcn
        20
    geekvcn  
       2021-03-24 19:24:14 +08:00
    开个 gRPC 服务,websocket 不适合这种场景,要与时俱进
    geekvcn
        21
    geekvcn  
       2021-03-24 19:58:36 +08:00
    https://github.com/enmasseio/timesyn
    找到一个现成的库,不知道性能如何还没细看
    geekvcn
        22
    geekvcn  
       2021-03-24 19:59:50 +08:00
    还是传统的 websocket,应该轮询实现的
    ligolas
        23
    ligolas  
       2021-03-24 20:01:59 +08:00
    @Hoshinokozo 通信时间就用本地计时的差值就可以,至于精度,可以根据需求来呗,他的核心需求是客户端时间不准是因为没开 ntp 对时,所以估计是差异很大,需求可能只是要求一个跟服务器尽量统一的时间,如果精度要求不高,可以就用 Date 的差值其实也就可以了。如果需要精度高一些的,可以用 performance.now()
    xuanbg
        24
    xuanbg  
       2021-03-24 20:30:51 +08:00
    服务端渲染
    agdhole
        25
    agdhole  
       2021-03-24 20:48:18 +08:00
    很多网站都禁止时间不准的电脑访问,例如 y2b
    autoxbc
        26
    autoxbc  
       2021-03-24 20:50:43 +08:00
    @ligolas #10 自己的服务器,自己的前端,不需要 CORS 就可以读 headers
    sxlzll
        27
    sxlzll  
       2021-03-24 22:26:55 +08:00
    电脑时钟总是准的,存个基准时间比较差值呗
    indev
        28
    indev  
       2021-03-25 01:02:06 +08:00
    像 firebase 都会返回统一的服务器时间戳
    lmaq
        29
    lmaq  
       2021-03-25 07:16:35 +08:00
    ShinichiYao
        30
    ShinichiYao  
       2021-03-25 08:25:04 +08:00
    @agdhole 那以后移民火星的看不了片子了
    CEBBCAT
        31
    CEBBCAT  
       2021-03-25 08:42:53 +08:00 via Android
    @ShinichiYao 时延和时间准确不一样哦。
    @agdhole 说的应该是连接到 HTTPS 网站时加密通信失败带来的打不开
    yl20181003
        32
    yl20181003  
       2021-03-25 08:59:28 +08:00
    响应头上去取就可以了,后端配置下即可
    yazoox
        33
    yazoox  
       2021-03-25 10:25:21 +08:00
    @lmaq
    这个是直接发一个 http GET 请求就可以了?然后在返回的结果里面把 data.t 取出来?
    ```
    {"api":"mtop.common.getTimestamp","v":"*","ret":["SUCCESS::接口调用成功"],"data":{"t":"1616639029711"}}
    ```
    ligolas
        34
    ligolas  
       2021-03-25 10:44:52 +08:00
    @autoxbc 自己的前端是什么概念? cors 是浏览器端的机制,只要用户还在使用正常的,版本不是特别老的浏览器,读取 header 就必须遵守 CORS,你自己尝试一下不难
    yazoox
        35
    yazoox  
       2021-03-25 10:46:44 +08:00
    @lmaq
    试了一下,用 postman 客户端,http GET 可以成功。
    但是,用 postwoman,在线版 /PWA 版本,都是 404 。 奇怪, 我已经用 CORS 插件禁止了呢。
    ```
    Referrer Policy: strict-origin-when-cross-origin
    ```
    Yunen
        36
    Yunen  
       2021-03-25 13:57:52 +08:00
    @ShinichiYao 你放心,等你移民火星的时候,火星上的互联网公司估计早都建好机房了 XD
    xingguang
        37
    xingguang  
       2021-03-25 16:28:12 +08:00
    是不是可以换个思路,让后端来做时间之类的东西,既然要服务器的时间,那么让后端接受到接口的时候自己建立时间对象
    autoxbc
        38
    autoxbc  
       2021-03-25 19:57:57 +08:00
    @ligolas #34 CORS 是 Cross-origin resource sharing,这里根本就不 Cross-origin,不受这个限制
    ligolas
        39
    ligolas  
       2021-03-25 21:43:55 +08:00
    @autoxbc 我确定你没搞懂 CORS 里面的 Cross-Origin 指的什么场景,到底哪里会 Cross Origin,为什么要做这个限制。
    https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header,注意这篇文章的标题:CORS-safelisted_response_header,点开链接看一下,然后再好好理解下 CORS 的本质。
    autoxbc
        40
    autoxbc  
       2021-03-25 22:35:42 +08:00
    @ligolas #39 我读了文章,试着理解一下

    1. 当 A 站 的前端跨域访问 B 站的页面时,因为同源限制,读取的内容会被浏览器抛弃掉;
    2. 此时,如果 B 站的后端确认这些内容不是用户的机密,可以配置一个 CORS 标志,使得 A 站的前端可以读取这个内容;
    3. 文章说的是,即便配置了 CORS 标志,有些消息头仍然没有全部暴露给 A 站,这个过程会经历一个过滤器;
    4. 这个过滤器默认放行文章所述的 6 种消息头;以及,这个放行策略可以由 B 站进行扩充

    那么,回到问题,题主现在是 A 站的前端,需要从 A 站的响应里读取消息头,整个过程不需要跨域,所以不需要配置 CORS,自然更不需要管理 CORS-safelisted_response_header
    ligolas
        41
    ligolas  
       2021-03-25 23:29:20 +08:00
    @autoxbc 所以我前面指出你就没理解对 CORS 的设计目的。CORS 是浏览器行为,是为了防止在浏览器端发生泄漏,服务端只是配合。那么浏览器端怎么发生泄漏呢?那就是 js,也就是如果某一个 js 执行了一段代码,读取到了**被认为**可能泄漏隐私的消息,这时候再发起一个到第三方的请求(可以是 js,也可以是 img ),就相当于把信息传递出去了,这个过程就被认为发生了泄漏。那么浏览器怎么做呢?其中一点就是限制了默认情况下 js 可以读取的 response header 的字段,也就是给你的文章里面的那 6 个,其他的,就得服务器端配合配置了才能由 js 读取到,这里面就包括了 date 字段。(另外不要弄错了,你通过开发人员工具是能读到的,cors 保证的是 js 代码读取不到)
    autoxbc
        42
    autoxbc  
       2021-03-26 00:35:00 +08:00   1
    @ligolas #41 我觉得您可能认为 CORS 会同时作用于同域和跨域,并认为 CORS 是浏览器权限控制的全部内容,事实就如其名字,仅仅用来管理跨域访问

    对于同域消息头的访问,有这几个概念
    https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name
    这部分描述了哪些**请求**消息头是不能被脚本**修改**的

    https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_response_header_name
    这部分描述了哪些**响应**消息头是不能被脚本**修改**的

    https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/getAllResponseHeaders
    这是与本文最相关的部分,描述了同域状态下,哪些消息头是不能被脚本**读取**的

    事实上只有 Set-Cookie 和 Set-Cookie2 两个字段禁止读取,并不包含 Date

    这里有一篇文章有比较详细的讲解
    https://segmentfault.com/a/1190000004322487
    g0thic
        43
    g0thic  
       2021-03-26 09:54:13 +08:00
    按 2 楼说的 上 https 时间不对 用不了 前端就抛出个错误提示就好了。
    ligolas
        44
    ligolas  
       2021-03-26 10:28:49 +08:00
    @autoxbc 你是对的,我之前的实验有问题,执行的 js 是从 cdn 上取的,相当于没有测试过同源的情况。不过考虑到现在服务部署的方式,很多时候资源就是从 cdn 部署的,并不能保证跟主站同源,这个 CORS 还是很有可能需要的(就像我遇到的情况),非常感谢你指出了我的盲区。
    autoxbc
        45
    autoxbc  
       2021-03-26 22:18:52 +08:00
    @ligolas #44 讨论也加深了我对这块的理解。不过还是有点问题,跨域不是指**网页**和**脚本**在不同的域下,不同来源的脚本只要加载到页面里,有一致的完整的权限

    跨域指**网页**和脚本访问的另一个**网页**是不是在同一个域下,当跨域时,受 CORS 的策略的管理
    ligolas
        46
    ligolas  
       2021-03-28 11:40:09 +08:00
    @autoxbc 恩,在发完之后我继续回忆了我测试的场景,应该是主站(静态页),cdn 加载 js,然后 API,三个独立的域名,js 试图读取的是 API 的 response 的 header 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     844 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 22:31 PVG 06:31 LAX 14:31 JFK 17:31
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86