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

Meteor - Server pull data from all client forms?

我正在尝试为一个应该按以下方式工作的活动构建一个测验游戏。

我有一个游戏合集,其中有多个问题。这些也有不同的类型、答案和倒计时。

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

倒计时结束后,表单输入应该被禁用,我想收集所有连接到游戏的客户端的数据。

有没有办法在倒计时 运行 结束后在服务器端触发一个方法,以从服务器端的所有客户端提取数据,而无需在客户端提交?

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

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

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

该文档包含有关它是否已开始、倒计时长度和(重要!)当前剩余时间的信息。在服务器上更新倒计时,从而更新文档。

一个最小的例子是:

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

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

还可以在服务器上检查管理员是否触发 start/pause,关于 userId/roles。这使得其他客户无法 start/end 测验。

一旦时间到了,你在文档中写入一个标志(例如 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){
                //...
            });
        }
    });
});