简体   繁体   中英

Decrement a variable once a day - Javascript

I'm trying to decrement a variable once a day. I have written the following code for that.

 var counter = 10; //any value setInterval(function() { counter = counter - 1; }, 86400000); 

Is there a better or efficient way to achieve the same thing ?

PS : - I do not wish to use any libraries.

I don't see any problem in the way you write it. You use interval, ok, but this is not the worst evil you may do to set up the variable value.

You may think of another solution with a function which returns you the current counter.

var initialValue = 20000;

function getCounter() {
  return initialValue - Math.floor(Date.now() / 1000 / 60 / 60 / 24);
}

console.log(getCounter());

The difference is that it takes the current day number starting from the UNIX time beginning. Every day the day number will be increased, so the result of the function will be decreased by 1.

But still I don't see how this solution can be better than yours.

The only thing I see you miss is to set the initial value of counter variable.
I would write:

var counter = 1000; // or any useful value

setInterval(function() {
  --counter;
}, 24 * 60 * 60 * 1000); // this is more self-explanatory than 86400000, and, being evaluated just once, it will have a tiny effect on the performace of the script

I'm not totally sure why, but using setInterval like this makes me uncomfortable.

If I were to require this, I would use something like this approach:

var counter = 10;
var timeout = new Date();
setInterval(function(){
  if(new Date() >= timeout)
  {
    --counter; // the action to perform
    timeout = new Date(timeout.getTime() + 86400000); // update the timeout to the next time you want the action performed
  }
  console.log(counter);
},1000); // every second is probably way more frequent than necessary for this scenario but I think is a decent default in general

One thing that this allows is to, for example, set the next timeout to midnight of tomorrow rather than being locked in to "X seconds since the previous execution". The key is the inversion of control - the action itself can now dictate when it should next run.

Though I would probably abstract away the details behind an interface accepting a start, interval, and action.

Maybe use window.localStorage to save the last time, and if it is greater than 60*60*24 (seconds in a day) set the last time to this morning/now/1:00 and then decrease the value and save it.

Example:

var d = new Date();
var mins = -(1+d.getHours())*60+d.getMinutes();
var secs = mins*60+d.getSeconds(); // total seconds passed today from 1:00
var now = d.getCurrentTime():
var lastCheck = localStorage.getItem("lastCheck");
if (!lastCheck)
{
    localStorage.saveItem("lastCheck",now-secs); // beginning of today
}
var dayPassed = now - lastCheck > 24*60*60; // change to see if a day has passed
if (dayPassed)
{
    // save seconds
    localStorage.setItem("counter",localStorage.getItem("counter")-1);
    localStorage.saveItem("lastCheck",now-secs); // beginning of today
}

The biggest problem in my eyes is that you have to keep this one JS process running consistently for days at a time to have it do what you need. The world is not so perfect that things don't need an occasional reboot...including the average JS process.

Personally I would store a timestamp of my starting point, then (whenever I need to know how much time has elapsed) grab a new timestamp and use it to calculate how many days it has been. That way even if something interrupts my process I can still be right where I started.

It makes more sense to me to check how many days have passed since a specific date and decrement that number of days from the counter. Mostly just because I wouldn't expect anybody to leave the same page open without the need or want to reload for days on end. I would do something like this:

counter = 365; // original counter
var start = new Date(2016, 03, 20); // original date
var now = new Date();
var days = Math.floor(Math.abs(start.getTime()-now.getTime())/(24*60*60*1000))
counter -= days;

That way every time you visited the page, it would be decremented correctly. Note that this ignores any issues with leap days or time zones. The example above would have a counter of 360 for me. And then if you did expect it to be open for days, reload it automatically with:

self.setTimeout(function(){document.location.reload()}, 86400000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM