0

I have written a JavaScript function that I simply copy paste into a browser console and runs, all works great and is working exactly as I want it to.

Looks like:

function test(d) {
  // ....
}
    
test(num);

I'm looking to wrap this function with kind of like a "while" statement. Please do keep in mind I'm not the greatest with JavaScript, yet.

Basically, What I'm looking for is while its NOT 6:30PM EST... keep waiting and check again. The second it hits 6:30 PM EST, execute the script.

Can anyone help me with what the syntax would look like? I found a lot on Stack Overflow but the syntax isn't really making sense to me.

Any help would be greatly appreciated.

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
ledia
  • 1
  • 4
  • What runtime is this expected to be executed in? Do you have a dedicated machine that will run the script (or its host page)? In any case, questions on Stack Overflow are expected to be regarding a specific, answerable technical problem related to computer software development. While your question meets the last prong of this test, in no way does this question meet any other component of that test. The community will *not* write your code *for* you - you should instead edit your question to include your previous attempt(s) or even research you've undertaken in solving the problem. – esqew Mar 24 '21 at 18:12
  • 1
    Such a `while` loop would choke the browser. Take a look at https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout – Teemu Mar 24 '21 at 18:12
  • @zhulien, correct this is expected to run on my browser tab that i'll just leave open.. i did find a couple of setTimeout solutions for example [1] but i honestly dont feel comfortable using this solution as i dont understand exactly what it's doing.. I'm looking more of an explanation how one calculates using this setTimeout to get a value of do not run till exactly 6:30pm or anytime really [1] https://stackoverflow.com/questions/4455282/call-a-javascript-function-at-a-specific-time-of-day – ledia Mar 24 '21 at 18:23
  • Does it always have to execute in the browser or you just need to run some JS at regular intervals? Regarding the former, did you check this: https://stackoverflow.com/questions/24741530/in-javascript-how-can-i-have-a-function-run-at-a-specific-time? For the latter, you might look into `cron` and more specifically - `node-cron`. Doing it with a loop checking every second or so is a pretty lazy solution, not to mention unperformant and it will require you to run it in a separate web worker. [redacted]. – zhulien Mar 24 '21 at 18:23
  • The simplest way is to use `setTimeout` with calculated time offset between now and the desired date/time and this requires the script to be operational(leave your tab open). – zhulien Mar 24 '21 at 18:24
  • More context as to what i also have... i actually have a retry mechanism already, which checks and runs for every 5 minutes, looks like this: setTimeout("mc_book("+day+")", 60*5*1000); // 5 minutes but i'm trying to change this 5 minutes calculation with something more straight forward to just have it run at exactly the time i need instead of running every 5 minutes – ledia Mar 24 '21 at 18:50

2 Answers2

0

Okay, a couple of notes. If you're not required to run a script in the browser itself but simply run some JavaScript at specific intervals you should checkout some schedulers like cron and more specifically for JavaScript - node-cron.

A solution which revolves around checking "is it time, is it time,..." each second or so in a loop is a pretty bad way to do it.

  1. It is highly wasteful and poorly performant.
  2. It will block your script execution so you have to execute it in a separate process like a web worker.

The simplest way, without using any dependencies is to schedule your work manually using a combination of setTimeout and setInterval. Here is a pretty basic and unpolished solution which should get you going.

const msInSecond = 1000;
const msInMinute = 60 * msInSecond;
const msInHour = 60 * msInMinute;
const msInDay = 24 * msInHour;

const desiredTimeInHoursInUTC = 18; // fill out your desired hour in UTC!
const desiredTimeInMinutesInUTC = 30; // fill out your desired minutes in UTC!
const desiredTimeInSecondsInUTC = 0; // fill out your desired seconds in UTC!

const currentDate = new Date();

const controlDate = new Date(currentDate.getUTCFullYear(), currentDate.getUTCMonth(), currentDate.getUTCDate(), desiredTimeInHoursInUTC, desiredTimeInMinutesInUTC, desiredTimeInSecondsInUTC);
let desiredDate;

if (currentDate.getTime() <= controlDate.getTime()) {
    desiredDate = controlDate;
}
else {
    desiredDate = new Date(controlDate.getTime() + msInDay);
}

const msDelta = desiredDate.getTime() - currentDate.getTime();

setTimeout(setupInterval, msDelta);

function setupInterval() {
    actualJob();

    setInterval(actualJob, msInDay);
}

function actualJob() {
    console.log('test');
}

In short, it calculates the difference between the current time and the next possible upcoming time slot for execution. Then, we use this time difference to execute the desired task and further schedule executions on every 24h after that.

You need to provide values for desiredTimeInHoursInUTC, desiredTimeInMinutesInUTC and desiredTimeInSecondsInUTC. All of them should be in UTC (the normal difference between EST and UTC is -4 or in other words - (hour EST - hour UTC = -4). You can (and actually should) improve this solution to handle timezones and the time difference calculations in general more elegantly.

A caveat here is that it won't handle daylight saving for you so you should keep that in mind. You can tackle this easily by using a dedicated library like moment.js. Also, the code is simple and in this version doesn't support cases like skipping specific days and such. You can always extend it to handle those, though.

Lastly, every time you restart the script, it will schedule your function execution times properly so you don't need to keep your tab open at all times. As an added benefit, the solution is quite performant as it doesn't do checks continuously if the time for execution has come but schedules everything in advance and doesn't do any more checks after that.

zhulien
  • 5,145
  • 3
  • 22
  • 36
0

Something like this solves the issue.

const now = new Date();
const currentYear = now.getFullYear();
const currentMonth = now.getMonth();
const currentDay = now.getDate();
// start running 6:30 pm next day
const nextRunAt = new Date(currentYear, currentMonth, currentDay + 1, 18, 30);
const timer = nextRunAt.valueOf() - now.valueOf();
setTimeout(() => {
  // first run
  test(num);
  // run once a day at the same time (24 hours after first run)
  setInterval(() => test(num), 1000 * 60 * 60 * 24);
}, timer);