Reactive subscription based on current time in Meteor

In an application that allows real-time communication between clients, I want to integrate functionality that allows me to define messages that are delivered at future points in time.

In the following example, I can insert messages that are inserted directly into the template. However, I would like to only display messages that have a time less than or equal to the current time, but automatically display messages that have future time points as soon as the time is reached. For example, if I insert a message from the console that should be displayed in the future after 30 seconds by calling Meteor.call("createMessage", 30000, "hello in 30 seconds")

, the message should be automatically displayed after 30 seconds.

I started limiting the request in the publish function time: {'$lt': new Date()}

. However, I am having trouble making this reactive. I have tried several combinations of Tracker.autorun

and without success cursor.observe

.

Can anyone give me a hint on how to accomplish the desired reactivity in the following example:

1) html file

<body>
    {{> chat}}
</body>

<template name="chat">
 {{#each chatMessages}}
    {{time}} - {{message}} <br>
 {{/each}}
</template>

      

2) js file

//server and client 
Messages = new Mongo.Collection("messages"); //{time: Sun Nov 02 2014 22:17:32 GMT+0100 (CET), message: "hello"}

//server
if(Meteor.isServer){
  Meteor.methods({
    'createMessage': function(timeOffset, message){
      Messages.insert({
        time: new Date(new Date().getTime() + timeOffset),
        message: message
      });
    }
  });

  Meteor.publish("messages", function(){
    return Messages.find({
      //time: {'$lt': new Date()}
    });
  });
}

//client
if (Meteor.isClient) {
  Template.chat.helpers({
    chatMessages: function(){
      return Messages.find({});
    }
  });

  Tracker.autorun(function (){
    mySub = Meteor.subscribe('messages');
  });
}

      

+3


source to share


2 answers


If Date () was a reactive data source it would work, but it isn't.

You can create a server side timer that will handle it. Best design i see id: choose next date in the future and set timer with time difference and also get following message. Of course it depends on how your application is performing.



More on Timers in Meteor: https://docs.meteor.com/#/full/timers

+1


source


Reactivity means that a view reflects the data sources used to create that view, update when those sources change, and only then (usually).

Therefore, if we want to accomplish what is described using reactivity, we must introduce a reactive change when the message is live (the outlined model has no such change).

There are two ways to achieve this that I can think of:



  • Add an 'isLive' field to the message and the server will change it at the right time using temporary callbacks and Meteor.startup

    (to avoid losing messages in case of reboot). A bit tricky but clean and efficient (if implemented correctly).
  • Add variable currentDate Session

    and use Meteor.setInterval

    etc. on the client to keep it as up to date as you need (since session variables are reactive).

In the second option, the user can simply change their system clock or use the javascript console to access future messages. In addition, reactive events at a given interval seem rather contrived if the interval is not meaningful to the problem area itself (for example, a calendar application changes the "today" session variable used to draw a red circle every midnight).

A simpler (better?) Non-reactive solution might be to just display future messages as hidden elements and use javascript timers to show them at the right time. But it all depends on what you are dealing with, of course.

+1


source







All Articles