Node.js scheduling function in conditional statement - javascript

I'm working on a project on Node.js. I want to execute some conditional code portion after waiting for five minutes since the last code does. I only need it to run once that way (not everyday or ...). The rest of the code will take over but when it ticks five minute, that will execute. Can I accomplish this?
EDIT: The code from Abdennour TOUMI partially works. But his way of denoting the minute by the variable didn't work for me. So I made the following edit according to the example from the module's page.
var schedule = require('node-schedule');
var AFTER_5_MIN=new Date(new Date(new Date().getTime() + 5*60000))
var date = new Date(AFTER_5_MIN);
var j = schedule.scheduleJob(date, function() {
if(condition1){
// Runned once --> Thus, you need to cancel it
// code here, than code to run once
j.cancel();
}else{
//it will be repeated
}
});

Your mistake is use 5 fields & the right is 6 fields .
* 0 * * * * --> For each hour at the 0 minute of that hour.
To start after 5 minutes , you could calculate the minute of hour after 5 minutes :
var schedule = require('node-schedule');
var AFTER_5_MIN=new Date(new Date(new Date().getTime() + 5*60000)).getMinutes();
var j = schedule.scheduleJob(`* ${AFTER_5_MIN} * * * *`, function() {
if(condition1){
// Runned once --> Thus, you need to cancel it
// code here, than code to run once
j.cancel();
}else{
//it will be repeated
}
});

Is there any reason you can't use setTimeout()?
const WAIT_TIME = (60 * 5) * 1000; //5 Minutes
var timer = setTimeout(function(){
console.log('Cron job works!')
}, WAIT_TIME);
/*
* If conditions change in this five minutes and you need to cancel executing
* the callback above, you can clear the timer
* clearTimeout(timer);
*/

Related

is it possible to fix one time using momentjs?

I am trying to fix one time and that time is current time + 10 minutes and i wanted to use a condition where when the current time is equal to the set time it will run my logic is it possible?
I have tried using moment but not able to completely solve the problem
here is my tried solution
const currentTime = momentTz().tz("Asia/Kolkata");
console.log(currentTime.valueOf());
const notificationTime = momentTz()
.tz("Asia/Kolkata")
.add(10, "minutes")
.valueOf();
// console.log(currentTime);
console.log(notificationTime);
// i want to run in this way
if(notificationTime === currentTime.valueof())
{
//notiifcation send}
How will code come to know to run script after some time?
You should use setTimeout for this
Like
setTimeout(() => {
// your code which has to be executed after 10 minutes
}, 1000 * 60 * 10)
Or if you want check after some intervals you can use setInterval
Like following code will check for condition after every minute
var myInterval = setInterval(() => {
const currentTime = momentTz().tz("Asia/Kolkata");
if (notificationTime <= currentTime.valueof()) {
//notiifcation send
clearInterval(myInterval)
}
}, 1000 * 60)

Reload html page at every tenth minute

I am trying to update a web-page at every tenth minute 7:40...7:50, etc. How do I do this?
Here is my code:
<body onload="checkTime()">
function checkTime(){
var unixTime = Date.now() / 1000;
var partTenMinuteTime = unixTime%600;
var time = unixTime - partTenMinuteTime + 600;
var difference = (time-unixTime)*10000;
console.log(difference);
setInterval(location.reload(),15000)
}
This is all I have, everything else I have tried does not work. I am using location.reload();
My problem is where this function gets called and how to implement it.
Here you can get nearest 10th min
let getRoundedDate = (minutes, d=new Date()) => {
let ms = 1000 * 60 * minutes; // convert minutes to ms
let roundedDate = new Date(Math.round(d.getTime() / ms) * ms);
return roundedDate
}
console.log(getRoundedDate(10))
Now you can use setInterval or in recursive setTimeout
You can get the minutes of the current hour and check how many minutes there are until the next 10-minute mark and use setTimeout. Your updatePage method should also continue to use call itself with setTimeout, if you are using AJAX to refresh the page (which makes more sense than reloading).
function updatePage(){
//update page
setTimeout(updatePage, 10 * 60 * 1000);
}
const now = new Date;
const nextDate = new Date;
nextDate.setFullYear(now.getFullYear());
nextDate.setDate(now.getDate());
nextDate.setMonth(now.getMonth());
nextDate.setHours(now.getHours());
nextDate.setMinutes(Math.ceil(now.getMinutes()/10)*10);
setTimeout(updatePage, nextDate - now);
You were very close with the solution in your question.
A couple of things to note:
You don't need setInterval(), but can use setTimeout() instead. After the page is reloaded, you will get a new timeout.
The callback you pass to setInterval() or setTimeout() needs to be a function and not a function call. If you include a function call, it will be executed immediately and not wait for the timeout or interval.
There is no need to create additional intervals to be able to correctly determine the 10 minute mark, as proposed in other answers to this question. You can correctly determine the correct time to call the reload action by doing the calculation you had in your question.
I'm aware that there are situations where you have too little control over the server code to be able to convert to AJAX, but if possible AJAX or websocket solutions should be preferred over reloading the page.
function reloadAfter(minutes) {
const millisToWait = minutes * 60 * 1000;
const millisLeft = millisToWait - (Date.now() % millisToWait);
setTimeout(() => location.reload(), millisLeft);
}
addEventListener('load', () => reloadAfter(10));
Why reload the page at all? Just use AJAX to query what you need. Here's code you could use to do your AJAX query, or reload the page... the later being a bad practice:
function onTenMin(func){
const m = 600000;
let i = setTimeout(()=>{
func(i); i = setInterval(()=>{
func(i);
}, m);
}, m-Date.now()%m);
}
addEventListener('load', ()=>{
onTenMin(interval=>{ // if you want you can pass the interval here
const dt = new Date;
console.log(dt.toString());
});
}); // end load
Just pass the function you want to onTenMin.
What's happening here?
Date.now() gives you milliseconds since January 1, 1970, 00:00:00 UTC. 600000 milliseconds is 10 minutes. % is the remainder operator, so it gives you the milliseconds remaining after division of the 600000. 600000 minus that remainder gives you how many more milliseconds until the next ten minute time. When that timeout happens it executes the function you pass to func then sets an interval which executes every 600000 milliseconds, passing the interval to func.
You can use a meta refresh instead don't burden the engine with timers
<meta http-equiv="refresh" content="600">
10 minutes = 600 seconds, so... This would automatically refresh your page every 10 minutes exactly.
Update
Every Exact 10th Minute Of An Hour
var tick = 10*60*1000,
tock = tick - Date.now() % tick;
setTimeout( "location.reload()", tock );
var tick = 10 * 60 * 1000,
tock = tick - Date.now() % tick;
setTimeout("location.reload()", tock);
//-----show something on the page----
with(new Date(tock))
document.write("Reloading in: " +
getMinutes() + " min, " +
getSeconds() + " sec, " +
getMilliseconds() + " mil."
);

How to convert a string to time in javascript

I'm trying to create a countdowntimer in Javascript. There are a lof of examples on the internet. I'm trying to adjust these to my own needs. I want a countdown timer that, when started, countsdown to the whole hour. For example, if I run the code at 13:15 it wil count down to 14:00.
The problem I have is getting the time to countdown to.
var cd = new Date("Jan 5, 2021 15:37:25").getTime();
In the above example you have a defined date. I'm trying to change this to a time to the first upcoming hour. Below is what I have:
var countdowndate = newDate("cd.getMonth, cd.getYear (cd.getHour + 1):00:00").getTime();
This isn't working. What am I doing wrong here? Any help is appreciated.
Here's a very expressive way of solving this:
Get the current time stamp, floored to the last full minute.
Get how many full minutes remain until the next hour, transform to milliseconds.
Sum up the results of 1 and 2.
function getBeginningOfNextHour() {
const msPerMinute = 60 * 1000;
const currentDate = new Date();
const currentDateTimestampRoundedToMinute = Math.floor(+currentDate / msPerMinute) * msPerMinute;
const msUntilNextHour = (60 - currentDate.getMinutes()) * msPerMinute;
return new Date(currentDateTimestampRoundedToMinute + msUntilNextHour);
}
console.log(getBeginningOfNextHour());

"infinite" setinterval function "timing out"

having a slightly weird issue that I cant figure out. Ive set up a javascript timer, all it does is repeats an interval every second that checks the difference between 2 dates and displays the results. All seems fine, however when leaving the browser open for several minutes (not touching it.. literally walking away for a while), it seems to "time out" and stop functioning. No console error messages or anything, the code just stops executing.. Was wondering if anyone had any idea what could be causing this? Is my code the issue or is this a built in browser function to stop js functions if there is no input from the user on a page for a certain time?
edit sorry should mention this timer is set to run for around 40 days at the moment so it will never realistically meet the clearinterval statement in a user session. The future date variable im adding to the function is a dynamic unix timestamp from PHP for a date which is roughly 40 days in future. Currently set to 1444761301.88
function MModeTimer(futureDate) {
zIntervalActive = true;
var currentTime = new Date().getTime() / 1000;
var timeRemaining = futureDate - currentTime;
var minute = 60;
var hour = 60 * 60;
var day = 60 * 60 * 24;
var zDays = Math.floor(timeRemaining / day);
var zHours = Math.floor((timeRemaining - zDays * day) / hour);
var zMinutes = Math.floor((timeRemaining - zDays * day - zHours * hour) / minute);
var zSeconds = Math.floor((timeRemaining - zDays * day - zHours * hour - zMinutes * minute));
if (zSeconds <= 0 && zMinutes <= 0) {
console.log("timer in negative");
// timer at zero
clearInterval(zTimeInterval);
} else {
if (futureDate > currentTime) {
console.log("timer interval running");
// changes html as part of function
}
}
}
zTimeInterval = setInterval(function() {
MModeTimer(zNewTime)
}, 1000);
This line:
clearInterval(zTimeInterval);
Is clearing the interval when the condition:
if (zSeconds <= 0 && zMinutes <= 0) {
Is met.
And as per the log you've wrote inside, that would be wrong. You are checking that zSeconds and zMinues are less or equal to 0. So when both are 0, the interval will be cleared.
Edit
As per your edits and explanations, may I suggest adding a console log that i'ts not inside any condition?:
function MModeTimer(futureDate) {
console.log('running');
//... rest of your code
That way you can make sure if the interval is running, maybe your conditions are not being TRUE after a while and you won't see any log, but the interval would be still running.

Multiple countDown timers on a single page in a meteor app

I am struggling to get multiple countdown timers displayed in a meteor app.
AuctionExpireIn is a date in the format - 2015-03-23T17:17:52.412Z.
Have a auctionItems collection , displaying 3 rows of auction items in auctionItem template.
While the target date is different for each of the auction items, what I am seeing is all the three rows have the same countdown timer . Apparently the session is not tied to each of the records and the same session value is being displayed for all the three rows.
How do I get different rows to display countdown timer based on the target data that each auction item document has?
Appreciate all the help.
Template.auctionItem.helpers({
AuctionExpireIn : function() {
var target_date = new Date(this.AuctionExpireIn).getTime();
//alert (target_date);
// variables for time units
var days, hours, minutes, seconds;
// update the tag with id "countdown" every 1 second
setInterval(function( ) {
// find the amount of "seconds" between now and target
var current_date = new Date().getTime();
var seconds_left = (target_date - current_date) / 1000;
var countdown ='';
// do some time calculations
days = parseInt(seconds_left / 86400);
seconds_left = seconds_left % 86400;
hours = parseInt(seconds_left / 3600);
seconds_left = seconds_left % 3600;
minutes = parseInt(seconds_left / 60);
seconds = parseInt(seconds_left % 60);
// format countdown string + set tag value
countdown= days + "d, " + hours + "h, " + minutes + "m, " + seconds + "s";
Session.set ('countdown', countdown);
}, 1000);
return Session.get('countdown');
}
});
You can tie each countdown timer to an instance of your auctionItem template. The below works as a proof-of-concept; each template will pick a random number from 1 to 10 and count down to 0. To apply it to your case, just replace the random number with the moment.js difference between this.AuctionExpireIn and new Date() (which I did not look up because I don't know it offhand).
Template.auctionItem.created = function(){
var self = this;
var num = Math.floor(Math.random() * 10);
this.remaining = new ReactiveVar(num);
this.interval = Meteor.setInterval(function(){
var remaining = self.remaining.get();
self.remaining.set(--remaining);
if (remaining === 0){
Meteor.clearInterval(self.interval);
}
}, 1000);
}
Template.auctionItem.helpers({
remaining: function(){
return Template.instance().remaining.get();
}
});
One point I noticed from the efforts above is you don't want to try to set the counters from a helper; just get the counters from a helper.
You can do this in a spacebars helper using ReactiveVar or Session. This example outputs the current time every second.
Template.registerHelper('Timer', (options)->
now = new Date()
reactive = new ReactiveVar(now.getTime())
Meteor.setInterval(()->
now = new Date()
reactive.set now.getTime()
,1000)
return reactive.get()
)
I'm not sure if the above is all of your current logic for your application, but based on what you have provided, the issue seems to be that you are using a single Session variable to keep track of the remaining time for three different auction items. If you need to use Session in order to keep track of your remaining times for the three different auction items, you should use three separate Session variables to do so, for example:
Session.set('auctionItemOne');
Session.set('auctionItemTwo');
Session.set('auctionItemThree');
But honestly, this is not the best way to go about solving this problem. Instead, I would recommend creating a simple template helper that takes in the end date/time for an auction item and outputs the appropriate string to describe the amount of time remaining. This can be easily accomplished with a library such as Moment.js. In order to implement this solution, do something like the following:
// Template
<template name="auctionItem">
{{timeRemaining}}
</template>
// Template Helper
Template.auctionItem.helpers({
timeRemaining: function() {
// Call appropriate Moment.js methods
// Return the string returned by Moment.js
}
});
I hope that this helps point you in a better direction for how to handle your situation. Please let me know if you need any further explanation or assistance.

Categories

Resources