在Meteor中将服务器时间显示在客户端上

11
使用Meteor,如何高效地在客户端上保持一个运行的时钟(h:m:s),并显示服务器的时间?
我找到的JavaScript/PHP答案通常涉及定期获取服务器时间并计算与客户端之间的差异。
在Meteor中会是什么样子呢?
更新:自我最初发布这个问题以来,很多事情已经发生了变化。如果您想要一个预先构建好的解决方案,我建议看看@mizzao的Meteor Timesync。在控制台中运行meteor add mizzao:timesync即可安装它。
5个回答

21

在这段关于Spark的演示中,David Greenspan展示了如何获取客户端时间,大约是在14:30左右。我稍微修改了这段代码以获取服务端时间:

Javascript:

if (Meteor.isClient) {
    Meteor.startup(function () {
        setInterval(function () {
            Meteor.call("getServerTime", function (error, result) {
                Session.set("time", result);
            });
        }, 1000);
    });

    Template.main.time = function () {
        return Session.get("time");
    };
}

if (Meteor.isServer) {
    Meteor.methods({
        getServerTime: function () {
            var _time = (new Date).toTimeString();
            console.log(_time);
            return _time;
        }
    });
}

同时需要翻译的内容:

<body>
  {{> main}}
</body>

<template name="main">
  {{time}}
</template>

天啊,你说得对。我修改了他的代码并编辑了我的答案。 - TimDog
我之前给你的代码投了反对票,但现在已经改为赞成票了! - Sjoerd Visscher
为什么每秒钟都要调用getServerTime?获取服务器时间后,使用本地时间考虑差异,然后从onCreated开始继续不是更好吗? - Abhishek Maurya

8
这个帖子里有非常好的信息。我把所有内容整理成了一个智能包,适用于Meteor:

https://github.com/mizzao/meteor-timesync

除了已有的内容外,我添加了两个主要功能:
  • 使用类似NTP的数学方法更准确地计算服务器/客户端偏移量,而不是仅仅对比客户端和服务器时间并忽略往返时间。
  • 能够在模板和响应式计算中使用服务器时间戳来显示值,并自动更新。
如果您有更好/更有效的计算和维护偏移量的想法,欢迎在此基础上开展工作。

太棒了,我会去看看的。 - Daniel Jonce Evans

6

感谢 @TimDog 的帮助。我稍作修改代码,现在客户端仍然可以显示运行时钟,但只需要定期检查服务器。以下是我的代码:

客户端代码:

  Meteor.startup(function () {

    function setServerTime(){

      //get server time (it's in milliseconds)
      Meteor.call("getServerTime", function (error, result) {

        //get client time in milliseconds
        localTime = new Date().getTime();

        //difference between server and client
        var serverOffset = result - localTime;

        //store difference in the session
        Session.set("serverTimeOffset", serverOffset);

      });
    }

    function setDisplayTime(){
      var offset = Session.get("serverTimeOffset");
      var adjustedLocal = new Date().getTime() + offset;
      Session.set("serverTime", adjustedLocal);
    }

    //run these once on client start so we don't have to wait for setInterval
    setServerTime();
    setDisplayTime();

    //check server time every 15min
    setInterval(function updateServerTime() {
      setServerTime();
    }, 900000);

    //update clock on screen every second
    setInterval(function updateDisplayTime() {
      setDisplayTime();
    }, 1000);

  });

  //pass the clock to the HTML template
  Template.register.clock = function () {
    return new Date(Session.get("serverTime"));
  };

服务器代码:

Meteor.methods({

    //get server time in milliseconds
    getServerTime: function () {
        var _time = (new Date).getTime();
        console.log(_time);
        return _time;
    }

  });

0
只需订阅一个普通的集合并将日期放入其中:(无往返计算)
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';

export const ServerDate = new Mongo.Collection(null);

if (Meteor.isServer) {
  // This code only runs on the server
  Meteor.publish('serverDate', function serverDatePublication() {
    return ServerDate.find({});
  });
  console.log('<ServerDate>:', new Date());
  Meteor.setInterval(updateDate, 1000 * 1);
}

function updateDate() {
  // Clean out result cache
  ServerDate.remove({});
  ServerDate.insert(new Date());
}

0
作为对这个问题的跟进,这会影响性能吗?我们每秒都在计算偏移量,并根据此重新计算Session。
这是否意味着任何依赖于Session的其他内容也会每秒重新计算?
将其设置为其他内容可能更好吗?
还是只需创建一个方法,根据需要进行本地日期调整,而不是设置间隔和会话变量。
让我知道你发现了什么。

你的实现在这里,对吧?(https://gist.github.com/zeroasterisk/7018221)。我认为客户端可以较少计算偏移量的频率,但是需要有一个反应式服务器时间方法,每秒重新计算一次偏移量。这将允许客户端应用程序显示实时的滴答声。我会考虑将其转化为智能包。 - Andrew Mao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接