场景是大量客户端电脑时间都不准,也没有时间同步,只能在程序里请求后端时间接口获取真实时间。
现在想法是程序只取一次服务器时间,然后在客户端模拟一个时间出来,关键要能支持 new Date 获取这个模拟时间,而且这个模拟时间能一直自动继续走。
这样的需求有啥好用的库吗?
1
lasuar 2021-03-24 12:13:46 +08:00
前端会 像服务器一样时刻运行着?
|
2
zvcs 2021-03-24 12:14:45 +08:00 via iPhone 2
加个 https 。如果他们时间不准就用不了
|
3
vinsony OP 我意思是程序运行的时候从服务器取一次时间
|
4
zhfapiu 2021-03-24 12:16:48 +08:00
计算服务端与客户端时间戳的差值,保存在前端
|
5
MakeItGreat 2021-03-24 12:17:53 +08:00 via Android 1
如果客户端的时间和服务器是有差值但是差值不变
那么根据两者固定的差值计算 |
6
jinsongzhao 2021-03-24 12:20:45 +08:00
没有什么库,因为需要由服务端配合, 你的服务端可以是 java 的,c#的,或者时间服务等等. 而客户端如果直接修改电脑时钟,又需要权限. 其实思路也非常简单, 自己实现好了. 服务端返回时间, 客户端本地时间和服务端时间做一个差值, 然后显示时间时,始终加上这个差值. 也不用什么定时同步, 客户端不会连续工作几十天,也不会几个小时就跑出几秒的误差
|
7
shenyuzhi 2021-03-24 12:23:31 +08:00
window.Date = function() {...}
|
8
opp 2021-03-24 12:44:24 +08:00 via Android 1
轮询吧,一次差值不靠谱。因为本机时间除了用户修改外,本身也会跳变,具体可搜下闹钟失效之类的案例。
|
9
chenqh 2021-03-24 12:47:29 +08:00
每次 api,都把服务器时间返回回去?
这个问题我也遇到过 |
10
ligolas 2021-03-24 12:53:00 +08:00
response header 里面默认就带有服务器时间的,Date 字段,但是因为 CORS 的原因,你默认读不到,可以在服务器端配置一下 cors 头,你就可以读到了,这个时间再加上通信的时间,就比较准确了
|
11
seki 2021-03-24 12:54:36 +08:00 1
实现个 ntp 算法
|
12
zhuweiyou 2021-03-24 13:21:20 +08:00
进来的时候 请求后端拿到服务器时间, 然后本地也 new Date, 做差值,
是有误差 但是差值是不变的. 后续只要 new Date + 差值 即可 |
13
fumichael 2021-03-24 13:59:06 +08:00
#10 response header +1
|
14
66beta 2021-03-24 14:02:37 +08:00
讲真,大部分项目 http 请求都是封装好的,拿不到 header
存差值比较合理 |
15
tiedan 2021-03-24 14:05:49 +08:00
所有接口加个默认字段也行
|
16
zhs227 2021-03-24 14:34:46 +08:00
存差值,多次按远近加权平均。
|
17
hailun3202475 2021-03-24 16:46:11 +08:00
我们之前的方案是 websocket 走心跳,假如每五秒一次心跳,每次心跳服务端都返回服务端时间,前端拿到时间做每次校验修正,前端时间也时刻在走
|
18
Hoshinokozo 2021-03-24 16:49:17 +08:00
@ligolas 通信的时间要怎么拿到呢?
|
19
jmk92 2021-03-24 18:32:15 +08:00
据我了解,一些用户机器的时间不准,即使同步了时间,可能还是过一天差一点,过不几天又不准了。
这个要牵扯到 CPU 时钟之类的,连他的机器都无法准确计算时间,你通过 js 算法 sleep 计算时间只会更不准。 所以只有跟服务器通信才是王道,websocket 是最优解,轮训对服务器压力大,也可以通过 10-30 秒一轮询,计算一下和本机的差值,时间等于差值+他的本地时间。 |
20
geekvcn 2021-03-24 19:24:14 +08:00
开个 gRPC 服务,websocket 不适合这种场景,要与时俱进
|
21
geekvcn 2021-03-24 19:58:36 +08:00
https://github.com/enmasseio/timesyn
找到一个现成的库,不知道性能如何还没细看 |
22
geekvcn 2021-03-24 19:59:50 +08:00
还是传统的 websocket,应该轮询实现的
|
23
ligolas 2021-03-24 20:01:59 +08:00
@Hoshinokozo 通信时间就用本地计时的差值就可以,至于精度,可以根据需求来呗,他的核心需求是客户端时间不准是因为没开 ntp 对时,所以估计是差异很大,需求可能只是要求一个跟服务器尽量统一的时间,如果精度要求不高,可以就用 Date 的差值其实也就可以了。如果需要精度高一些的,可以用 performance.now()
|
24
xuanbg 2021-03-24 20:30:51 +08:00
服务端渲染
|
25
agdhole 2021-03-24 20:48:18 +08:00
很多网站都禁止时间不准的电脑访问,例如 y2b
|
27
sxlzll 2021-03-24 22:26:55 +08:00
电脑时钟总是准的,存个基准时间比较差值呗
|
28
indev 2021-03-25 01:02:06 +08:00
像 firebase 都会返回统一的服务器时间戳
|
29
lmaq 2021-03-25 07:16:35 +08:00
|
30
ShinichiYao 2021-03-25 08:25:04 +08:00
@agdhole 那以后移民火星的看不了片子了
|
31
CEBBCAT 2021-03-25 08:42:53 +08:00 via Android
|
32
yl20181003 2021-03-25 08:59:28 +08:00
响应头上去取就可以了,后端配置下即可
|
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"}} ``` |
34
ligolas 2021-03-25 10:44:52 +08:00
@autoxbc 自己的前端是什么概念? cors 是浏览器端的机制,只要用户还在使用正常的,版本不是特别老的浏览器,读取 header 就必须遵守 CORS,你自己尝试一下不难
|
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 ``` |
36
Yunen 2021-03-25 13:57:52 +08:00
@ShinichiYao 你放心,等你移民火星的时候,火星上的互联网公司估计早都建好机房了 XD
|
37
xingguang 2021-03-25 16:28:12 +08:00
是不是可以换个思路,让后端来做时间之类的东西,既然要服务器的时间,那么让后端接受到接口的时候自己建立时间对象
|
38
autoxbc 2021-03-25 19:57:57 +08:00
@ligolas #34 CORS 是 Cross-origin resource sharing,这里根本就不 Cross-origin,不受这个限制
|
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 的本质。 |
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 |
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 代码读取不到)
|
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 |
43
g0thic 2021-03-26 09:54:13 +08:00
按 2 楼说的 上 https 时间不对 用不了 前端就抛出个错误提示就好了。
|
44
ligolas 2021-03-26 10:28:49 +08:00
@autoxbc 你是对的,我之前的实验有问题,执行的 js 是从 cdn 上取的,相当于没有测试过同源的情况。不过考虑到现在服务部署的方式,很多时候资源就是从 cdn 部署的,并不能保证跟主站同源,这个 CORS 还是很有可能需要的(就像我遇到的情况),非常感谢你指出了我的盲区。
|