Ask coding questions

← Back to all posts
Run a function every week in JS or node.js?
EthanBlesch (8)

I have a game and I want to have the high scores reset every week, is there a way to do this? preferably done with node.js and compatible with express.

Comments
hotnewtop
Baconman321 (1097)

Here is something you can do:

const weeklyRun = (weekName, callback) => {
  let isRun = false;
  const weeknames = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
  const check = () => {
    const date = new Date();
    if(weeknames[date.getDay()] === weekName.toLowerCase() && !isRun){
       callback();
       isRun = true;
    }
    else if(weeknames[date.getDay()] !== weekName.toLowerCase() && isRun){
      //Reset isRun to false for the next time that day of the week rolls around
      isRun = false;
    }
    globalThis.setTimeout(check, 1);
  };
  check();
};
//console.log "hello world" every monday...
weeklyRun("monday", () => console.log("hello world"));

The big problem is if your program falls asleep (or restarts). If it does, the isRun is reset, meaning that the program will start over again and possibly do the callback twice (especially if it is run on the same day that it is supposed to execute the callback)!

To compensate for this, you can use the replit database, which allows persistent storage - even if the repl shuts off.

Replit database IMO is very limited right now, but it is perfect for storing small key/value pairs in a database.

EthanBlesch (8)

@Baconman321 so what values would I need to save to and get from the replit database to prevent it from running multiple times?

Baconman321 (1097)

@EthanBlesch Just the "isRun" (you could name it whatever you like, but it has to function in the same way that the isRun var does in the code snippet I provided).

The only problem is restarting the program after it falls asleep.

It would be simple with only running that function once, you get a single key from the database that marks if it is run yet. If you want to run multiple tasks, however - you would need unique IDs as well as a way to retrieve them even after the program restarts (if it loses track of the IDs, then the database has it but you don't know the ID number so all is lost).

EthanBlesch (8)

@Baconman321 yeah, all I need to do is set the high scores back to 0 at the beginning of every week so your code should work great.

Baconman321 (1097)

@EthanBlesch Don't forget to mark it as the answer if my code is, truly the answer (which I assume it is, according to your response).

EthanBlesch (8)

@Baconman321 it says weeknames is not defined

Baconman321 (1097)

@EthanBlesch Sorry, I'll edit the answer.

There.

It just was caused due to me assigning the array to a variable named weekNames instead of weeknames (JS is case-sensitive).

Baconman321 (1097)

@EthanBlesch Now you can mark it as the answer (I fixed another problem as well).

EthanBlesch (8)

@Baconman321 also it logs isRun as null after a minute when I use this code and log isRun: const weeklyRun = (weekName, callback) => {
let isRun = false;

const weeknames = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
const check = () => {
db.get('isRun').then((value) => isRun = value)
console.log(isRun)
const date = new Date();
if(weeknames[date.getDay()] === weekName.toLowerCase() && !isRun){
callback();
isRun = true;
}
else if(weeknames[date.getDay()] !== weekName.toLowerCase() && isRun){
//Reset isRun to false for the next time that day of the week rolls around
isRun = false;
}
db.set('isRun', isRun)
globalThis.setTimeout(check, 1);

};
check();

};
it says false for a little bit then starts saying null try running it yourself

Baconman321 (1097)

@EthanBlesch You haven't set isRun in the DB yet.

At the beginning of the weeklyRun function, set isRun in the database to false.

This is somewhat buggy though, if it stops running on the day it is running that task it will run it again. It is up to you to edit the code, though - as IDK nodejs that much and this is an opportunity for you to learn :)

EthanBlesch (8)

@Baconman321 it still runs multiple times even when not run with db.set and db.get, its reeeeally buggy

Baconman321 (1097)

@EthanBlesch It really shouldn't (it works well for me). Invite me to your repl and I'll try to fix some things with it (it is hard to have an ongoing conversation here). I'm available for ~20 minutes, but that should be more than enough.

Baconman321 (1097)

@EthanBlesch I don't have much time now but I can change it when I can and leave comments explaining what I changed.

InvisibleOne (2975)

Well technically you could do this:

setInterval(function() {
  // do something every week
}, 604800000)

Which would make it do that function every week, but the real problem would be with making sure the repl is always running.

Baconman321 (1097)

@InvisibleOne Plus, I heard that setInterval and setTimeout gets inaccurate after about an hour.

InvisibleOne (2975)

True, I didn't think about that, it would slowly get off by a bit @Baconman321