4
For Javascript and Nodejs, there are n robust Cron style libraries, such as Node-cron. But they are complex too much for simple situations, are heavy to download in the browser or require an additional dependency on Nodejs, which makes them unviable in simpler cases.
I want to create a function that can:
- Accept the second, minute and time the routine is ready to provide new data.
- Check what time it is now on the client, and schedule the start of the
setInterval
for the first opportunity when the server has new data. - Define the range of
setInterval
as exactly the period between server updates. - Run in Nodejs environment and modern browsers and on IE8. In case you don’t know how to test in Nodejs, I test for you.
- There should be no additional dependency. No jQuery or Nodejs package.
- The code shall accept a range parameter of type try again in x seconds, and pass a callback to executed function so that if it returns exactly
false
, will try this one again until you returntrue
or arrive at the time of the next standard execution. Consider that the server may fail and always return error, but the client should avoid overwriting additional attempts!
Actual use example
The code below is responsible for synchronizing a table of a database with the executed browser or task Nodejs
/**
* Sincroniza o cliente com dados do banco de dados. Caso os dados sejam
* diferentes dos que o cliente já possuia antes, passa ao callback true
* do contrário, se percebeu que o servidor ainda não atualizou os dados
* retorna false
*
* @param {Function} [cb] Callback. Opcional
*/
function sincronizar(cb) {
var conseguiuSincronizar = false;
// Executa uma rotina de sincronização de dados
cb && cb(conseguiuSincronizar);
}
However, the database is only updated once every 15 minutes, that is, in minutes 0
, 15
, 30
, 45
hourly.
As saving in database can take some time, this routine would have to run every 15min
and a few seconds of delay, for example, each 15min5s
.
The problem when using setInterval
is that put to update every 15min, runs the risk that when the browser or the Nodejs task is initialized, there is a delay between the time when the client could get new information and the time when it is available. Define setInterval
in a period less than 15min would cause data loss.
Bootstrap
Below is a bootstrap of how the simplest example could be done.
function cron (cb, s, m, h) {
var start = 0, interval = 0;
/* Logica para calculo de start e interval aqui */
setTimeout(function () {
setInterval(cb, interval);
}, start);
}
You want a function that does
setInterval(func, 5*um_minuto)
, but synchronized with the clock? 12:30, then 12:45, that’s it?– Gustavo Rodrigues
Think of the example: a football site announces 15 minutes of active games metrics, but this site falls and your Crawler restarts frequently. How to make a Crawler that can start at any time prefer to access the page at times when it has updated data, without forcing a setTimeout every minute and running the risk of being banned? There are n practical examples of this, where a setInterval that takes into account the time is time is better than desperately getting data every instant.
– Emerson Rocha
If the update is done every 15min from 00h00min of the day, and by setTimeout with 15min of dalay, but the routine start at 12h14min, you would always run the function 14min after the information is available.
– Emerson Rocha
As soon as the user goes online, the time of the server is passed to him, time that is to run the first update and then time of repetition of the process. Already solved. If the guy is offline he will not download anything at all...
– Gabriel Gartz
Gabriel, for the sake of simplification, you don’t have to worry about the server passing the initial time. Simplify and think more about time being synchronized between the local machine and the server that is accessed. Javascript does not need to solve all problems
– Emerson Rocha
@Emersonrochaluiz And why can’t you just discount the refresh interval from past current time to the first scheduling? In your example, 15 - 14 = 1, the first execution would be scheduled in 1 minute, and the rest interval would be maintained in 15 minutes.
– Luiz Vieira
@Luizvieira that’s exactly what. I’m rewarding 50 points whoever does at least that. If you have more answers, the differential would be if the callback of the scheduled function returns false, it tries a few moments later. For simplification, assume that the
new Date()
ofjavascript
be synchronized to the desired time.– Emerson Rocha
One thing I still don’t understand in your question: do you want to minimize the check interval of the current time, or run as close as possible to the server updates? The
setInterval
tends to go lagging, so with time the trend is to update each time later in relation to the server, unless you check the timestamp constantly. Or maybe you’re looking for a compromise?– bfavaretto
Only later I realized that considering calculating the delay between steps is not a good idea and that it is better to give by default, so it tends to be interesting beyond the typical start time, optionally accept the explicit interval, like the basis of the answer I made there that needed to be improved. I believe that it would be best to only check current time when starting the function, it defines how much time to get to the first stage (here it is assumed that
new Date()
will be synchronized) and then passes a value tosetTimeout
what would you callsetInterval
, that would then call the function.– Emerson Rocha