Meteor - 服务器从所有客户端表单中提取数据?

时间:2017-07-25 09:22:51

标签: forms meteor server-side

我希望有人可以帮助我。

我尝试为一个事件构建测验游戏,该游戏应该按以下方式工作。

我有一个游戏集合,有多个问题。那些又有不同的类型,答案和倒计时。

管理员必须开始游戏,游戏开始第一个问题并设置倒计时。

倒计时后,forminput应该被禁用,我想从连接到游戏的所有客户端收集数据。

在倒计时运行之后是否有办法在服务器端触发方法从服务器端的所有客户端提取数据而不在客户端提交?

1 个答案:

答案 0 :(得分:2)

我在项目中使用了类似的东西,也许这是解决问题的方法。

服务器端计数器和模板级订阅

让您的客户订阅测验集合,其中每个文档代表当前的测验逻辑

该文件包含有关它已经开始的信息,倒计时长度和(重要!)当前剩余的时间。倒计时在服务器上更新,因此文档会更新。

最小的例子是:

  • started - 布尔值(以管理员方式触发测验)
  • 时间 - 数字(例如以秒为单位,倒计时的总长度)
  • timeLeft - 数字(这是剩下的当前时间,由柜台写入文档)
  • timeUp - 布尔值(触发发送结果)

为什么?因为您将更新服务器上的倒计时并将剩余时间写入文档。这消除了问题,客户端可以操纵他们的倒计时(因此也许剩下的总时间)并且他们将他们的时间与服务器而不是服务器同步。

对于userId / roles,可以在服务器上检查管理员触发启动/暂停的任何内容。这使得其他客户无法开始/结束测验。

一旦时间结束,你就会在文件中写一个标志(例如timeUp),时间到了。这又可以在客户端中反应性地触发模板事件,该模板事件使每个客户端调用服务器方法并将其结果发送到服务器。

使用模板级订阅的示例如下:

Template.quiz.onCreated(function() {
    const instance = this;
    instance.state = new ReactiveDict();
    instance.state.set('timeLeft', -1);
    instance.state.set('started', false);

    const quizId = /* ... params to load your quiz document */

    instance.autorun(function () {

        const subscription = instance.subscribe("quizpublication");
        if (subscription.ready()) {
            instance.state.set("loadComplete", true);
        }


        const quizDoc = Quiz.findOne({})
        if (!quizDoc) return; //skips until subscriptions are ready
        if (quizDoc.started && !intance.state.get("started") {
            Meteor.call("startQuiz", {_id:quizDoc._id}); // trigger the counter start on the server
            instance.state.set('started', quizDoc.started);
        }

        instance.state.set('timeLeft', quizDoc.timeLeft); //updated on the server, updated here

        if (quizDoc.timeUp) {
            Meteor.call("sendMyQuizresults", {/* your results from the form input*/}, function(err, res){
                //...
            });
        }
    });
});