What would be the result if the callback function is not completed before the timeout of the setInterval function.
For example:
setInterval(function() {
// This block takes more than 5 seconds.
}, 4000);
Now the setInterval has a timemout of 4 seconds whereas the callback functions takes 5 seconds to complete. What would happend, would it wait for the function to complete or make execute the callback again in 4 seconds?
It will wait for the callback to complete, as JavaScript is single-threaded. If you run the below snippet, you will see that 'done' is printed every 5 seconds.
setInterval(function() {
let curr = new Date;
while(new Date() - curr <= 5000);
console.log('done');
}, 4000);
It depends.
If you put there some computations that happens to take 5 seconds (like looking for prime numbers or something), you'll lock the main thread and another call would be done only when it's unlocked, so in that case after about 5 seconds.
If the part that takes so long is for example a http request it will call the function every 4 seconds as it should. As far as I know there is no mechanism in setInterval that would check if function's promise is done or not.
So your setInterval has 2 parameters, a callback and the duration (4s)
There are a few things than can affect your interval:
your setInteval call a browser API which will start a timer to exactly 4 seconds. Once the timer triggers that 4 seconds, it will append your callback on the JS callback queue. Again, this happens exactly after 4s.
Once all the synchronous code will be executed, JS will start running the callbacks in the callback queue, one at a time.
To answer your question: if it's just the code that you posted, it will most likely take exactly 4 seconds. In case you have some heavy operation in your code that takes more than 4 seconds, that code may take longer since it will run only after.
Because of the event loop, the task queue and the single-threaded nature of JavaScript, it would always wait for the function to complete. Synchronous code is never canceled, unless the script is forcefully stopped.
The HTML standard says that timers must:
Wait until any invocations of [the timer initialization algorithm] that had the same method context, that started before this one, and whose timeout is equal to or less than this one's, have completed.
Other timers and browser/runtime tasks would also run between the function. But if the function is running on the main thread, the program would only receive events while the function is not running. In a browser, this would mean that the website would not be interactive for most on the time.
For those reasons, such functions with heavy synchronous computations should be run inside a Worker or split among several tasks (see How to queue a task in JavaScript?).
(I'm assuming "This block takes more than 5 seconds." means that the function returns after 5 seconds.)
Check this out I found my own answer.
What this does is, it spawns a thread to execute the callback function after every timeout that works seperately.
document.write('Part 1:<br>');
setInterval(function() {
var x = Date.now();
document.write(x + '<br>');
setTimeout(function() {
var y = Date.now();
document.write(y.toString() + ' : ' + (y-x).toString() + '<br>');
}, 5000);
}, 2000);
Related
Consider the two functions below, both async, one a brutal workload that takes a lot of time, and the other one a wait function that waits a precise number of seconds by setting a timeout.
async function Brutal_Workload()
{
for(var x = 0; x< 1000 * 1000 * 1000; x++)
{
}
}
async function Time_Wait(seconds)
{
var promise = new Promise((resolve, reject) =>
{
var msecs = Math.floor(seconds * 1000);
var timer =
setTimeout(
function()
{
clearTimeout(timer);
resolve();
},
msecs);
});
return promise;
}
Now, let's call the first function in a setInterval cycle
setInterval(
async function()
{
await Brutal_Workload();
console.log("BLIP");
}, 1000 / 30);
All as intended: despite the interval running at 30 calls per second, I only get 1 blip per second, because Brutal_Workload is choking it.
But when I use the other function...
setInterval(
async function()
{
await Time_Wait(1);
console.log("BLIP");
}, 1000 / 30);
I get 30 BLIPs per second.
The Time_Wait function, which works otherwise just fine outside of setInterval, doesn't seem to work here.
Any idea of what might cause this behavior?
Ok, rather than continue the back-and-forth in the comments, I'm just going to post this as an answer.
Javascript is both single-threaded and concurrent. I know you know this, but you don't seem to realize the implications. In your first function, you only see a console.log every so often, because your "brutal workload" blocks the only thread of execution until it completes, which means that regardless of what number you passed to setInterval not only is no other invocation running, the next bit of work isn't even being queued to run because your brutal workload is blocking the only thread of execution.
Understand, the runtime environment's setInterval runs on the same (only) thread as your code, the JS engine doesn't cheat and run your stuff in one thread and setInterval in another. So while brutal workload is doing its thing, setInterval itself, much less the function you passed to it, is not running at all. Using async and wrapping your brutal workload in a Promise makes essentially zero difference in terms of our discussion here, because brutal workload dominates.
So that explains the first example, so far so good. On to the second.
Unlike the first example, in the second there is no long-running chunk of code to tie up the thread of execution. So your callback to setInterval runs, dutifully registers a thing to run in a second, and yields control of the thread of execution, something that again the first example does not (and cannot do). Here the Promise and async/await actually does enable concurrency which it can't do in the first example because brutal workload is hogging the thread. So in a fraction of a second your callback to setInterval runs again, dutifully queues up another thing to run after a second has passed, and so on.
So after ~1 second that first queued up log happens, and then after a fraction of a second after that the second, and then so on. This doesn't happen in the first example because although you told setInterval to run 30x/sec brutal workload means that setInterval itself can't run to even queue your callback to be ran.
I have a node script which is supposed to utilize all the CPU resources a single node process could get. But I found setInterval to be too slow.
And sure enough I found this in the documentation:
When delay is larger than 2147483647 or less than 1, the delay will be
set to 1.
source: https://nodejs.org/api/timers.html#timers_setinterval_callback_delay_args
Now I wonder if there is a way to reduce the limit further or if there is an alternative function that I could use.
I can't just use a normal loop because there are other asynchronous things that need to run at the same time.
Edit:
Again: I can't just use a normal loop because there are other asynchronous things that need to run at the same time.
I'm not sure why this is so hard to understand.
While a normal loop is running, you are blocking the execution of everything else. It doesn't matter if you put the loop in another asynchronously executed function.
What does this mean?
Let's look at some examples:
setInterval(()=>{console.log('a')},1000) // asynchronous thing that needs to run in the background
while (true) {
// do whatever
}
What will this code do? It will block everything. console.log('a') will not be executed continuously.
setInterval(()=>{console.log('a')},1000) // asynchronous thing that needs to run in the background
setTimeout(()=>{
while (true) {
// do whatever
}
}, 1)
This will also block the execution of the intervals as soon as the while loop starts.
I believe the question belongs to node rather than to browser. You can use some of the following options (recursively/in loop) for reducing your delay time.
setImmediate
setImmediate - Schedules the "immediate" execution of the callback after I/O events' callbacks. Returns an Immediate for use with clearImmediate().
When multiple calls to setImmediate() are made, the callback functions are queued for execution in the order in which they are created. The entire callback queue is processed every event loop iteration. If an immediate timer is queued from inside an executing callback, that timer will not be triggered until the next event loop iteration.
It's from node guides:
setImmediate and setTimeout are similar, but behave in different
ways depending on when they are called.
setImmediate() is designed to execute a script once the current poll phase completes.
setTimeout() schedules a script to be run after a minimum threshold in ms has elapsed.
process.nextTick
The process.nextTick() method adds the callback to the "next tick
queue". Once the current turn of the event loop turn runs to
completion, all callbacks currently in the next tick queue will be
called.
From node guide
We recommend developers use setImmediate() in all cases because it's
easier to reason about (and it leads to code that's compatible with a
wider variety of environments, like browser JS.)
Thanks to Josh Lin for the idea to just run multiple intervals. I ended up with two simple wrapper functions for setInterval and clearInterval:
function setInterval2(cb,delay) {
if (delay >= 1)
return [setInterval(cb,delay)];
var intervalArr = [];
var intervalCount = Math.round(1/delay);
for (var i=0; i<intervalCount; i++)
intervalArr.push(setInterval(cb,1));
return intervalArr
}
function clearInterval2(intervalArr) {
intervalArr.forEach(clearInterval);
}
It works just like the original functions:
var count = 0;
// run interval every 0.01 milliseconds:
var foo = setInterval2(function(){
count++;
},0.01);
// stop execution:
clearInterval2(foo)
1 setInterval multiple times run more!
let count = 0,
by = 100,
_intervals = [],
timelimit = 100
for (let i = 0; i < by; i++) {
_intervals[i] = setInterval(() => count++, 1)
}
setTimeout(() => {
_intervals.forEach(x => clearInterval(x))
console.log(`count:${count}`)
}, timelimit)
2.setTimeout recurser run less!
let count = 0,
go = true
recurser()
setTimeout(() => {
go = false
console.log(`count:${count}`)
}, 100)
function recurser() {
count++
go && setTimeout(recurser)
}
3.requestAnimationFrame run less!
let count = 0,
go = true,
timelimit = 100
step()
setTimeout(() => {
go = false,
console.log(`count:${count}`)
}, timelimit)
function step() {
count++
go && requestAnimationFrame(step)
}
so as I know ,run setInterval multiple times, and I believe while will count more
You ask if it is possible to
run setInterval more than once per millisecond in nodejs
As you note in your question, this is not possible with setInterval, since there is always a minimum delay of at least 1 ms in node.js. In browsers, there is often a minimum delay of at least 10 ms.
However, what you want to achieve—to repeatedly run CPU-intensive code without unnecessary delay—is possible in other ways.
As noted in the answer by The Reason, setImmediate is a good option available in node.js. As setImmediate has limited browser support, and is unlikely to be widely supported in the future, there is another approach that also works in browsers.
While browsers enforce a minimum delay for setInterval and setTimeout, the delay for setTimeout is enforced from when the timer is set, not when it is run. If we use setTimeout repeatedly to call CPU-intensive code, we can make sure that a timer is always set 10–15 ms in advance (if the code takes at least 10–15 ms to run), thus reducing the actual delay to 0 ms.
The demo snippet below borrows code from this answer to demonstrate how the use of timers set in advance may make the delay smaller than what is enforced. In the browsers I tested, this usually results in a 0 ms delay.
// First: repeat runCPUForAtLeast50ms() 10 times
// with standard repeated setTimeouts and enforced delays
testTimeout(10, function(){
// Then: repeat runCPUForAtLeast50ms() 10 times
// using a repeated set of queued setTimeouts
// circumventing the enforced delays
testTimeout(10, false, true);
});
function testTimeout(repetitions, next, multiple) {
var delays = [];
var lastCheck;
var extraTimers;
function runner() {
if(lastCheck){
delays.push((+new Date) - lastCheck);
}
if(repetitions > 0) {
//process chunk
runCPUForAtLeast50ms();
//set new timer
setTimeout(runner);
} else if(repetitions === 0) {
//report result to console
console.log((multiple?
'Repeated multiple timers delays: ' :
'Repeated single timer delays: ') + delays.join(', '));
//invoke next() function if provided
next && next();
}
repetitions--;
lastCheck = +new Date;
}
setTimeout(runner);
if(multiple){
// make sure that there are always a fixed
// number of timers queued by setting extra timers
// at start
extraTimers = 10;
while(extraTimers--)
setTimeout(runner);
}
}
function runCPUForAtLeast50ms() {
var d = (+new Date) + 50;
while(+new Date < d);
}
I think you can solve your problem using async module... a way could be:
async.parallel([
(callback) => {
// do normal stuff
},
(callback) => {
// do your loop
}
], (err, results) => {
// ...
});
But take into account this note from the official documentation...
Note: parallel is about kicking-off I/O tasks in parallel, not about
parallel execution of code. If your tasks do not use any timers or
perform any I/O, they will actually be executed in series. Any
synchronous setup sections for each task will happen one after the
other. JavaScript remains single-threaded.
In short answer, you can't. There are some limitation of Javascript/Node as it is a single thread application. That's why you have async interrupts.
The long answer:
From the computer architecture's perspective, modern CPU and Kernel scheduling is not deterministic. If you want such fine grain control, I would suggest you look at MCU and embedded solutions that does not have a kernel scheduler. Because, your OS have many other processes and Kernel processes that takes up CPU time, so kernel scheduler have to keep scheduling different processes to be run on the CPU and meet many different demands.
Even with the set 1ms, when you try to measure, it is probably not 1ms (exact time depends on OS, hardware and amount of processes running on your computer).
Now, if you want to use all CPU resources, not possible.
But if you want to utilize as much as resources as possible, you can explore current programming pattern. For example, you can schedule 1 million threads (you machine probably won't be able to handle it), or some crazy large amount of processes and let your scheduler to be constantly putting process on your CPU, so there is no idle time and max out CPU utilization.
Alternatively, you can run CPU Stress tests, and those are designed to simply max out your CPU and keep it burning to high temperature -- make sure you have the cooling solution in place.
what could be the reason for a setTimeout to wait 2-4 times as long as configured to be executed?
var TIMEOUT = 700;
console.log("TIMEOUT", TIMEOUT);
var preTimeout = new Date();
setTimeout(function() {
console.log("timeout took:", new Date() - preTimeout);
}, TIMEOUT);
This results in timeout took: from 1200-4000 on a website.
setTimeout() doesn't mean execute the code after exactly N milliseconds. It rather means, don't execute the code for at least N milliseconds.
The asynchronous code such as the setTimeout() callback is put on an event loop queue until all syncrhonous code finishes executing, and then it's run. This includes any async code that gets run in the queue before the timeout period. Your callback can run only after all those are done.
Here's a small demo to show this using synchronous while loop:
https://jsfiddle.net/foxbunny/1a9rckdq/
Code like the one in the demo is what you'll hear people referring to as 'blocking'. This is because it blocks the event loop queue.
I've also written a somewhat long article on the topic if you want a throrough overview.
What's happening with that piece of code
var start = new Date();
setTimeout(function() {
var end = new Date();
console.log('Time elapsed with func1:',end - start, 'ms');
}, 500);
setTimeout(function() {
var end = new Date();
console.log('Time elapsed with func2:',end - start, 'ms');
}, 250);
while (new Date() - start < 1000) {}
Logs:
Time elapsed with func2: 1001 ms
Time elapsed with func1: 1017 ms
I was expected that func1 will be fire first because it's the first event to be added into the event queue. Then, due to the single thread nature of JS, wait until func1 returns and then executes the next event in the queue which is func2.
So, what's happening?
First off setTimeout() is asynchronous and non-blocking. That means when you call it, all it does is register the new timer and then immediately returns. So, when your code runs, it will follow these steps:
You register the func1 timer for 500ms.
You register the func2 timer for 250ms.
Each of the timers is added to a sorted data structure inside the timer portion of the event loop so it's easy for the event loop to know and check which timer is next to execute.
You start the while spin loop. That loop runs for about 1000ms.
When the while spin loop finishes, the Javascript interpreter gets to go back to the event loop to check if there is anything else to do. One of the things it checks (one of the phases of the event loop) is to see if there are any timers ready to run. It checks the head of the timer list and sees that its time has already passed by (meaning it is past time for it to run). So, it grabs the callback associated with that func2 timer and executes it. The func2 timer is at the start of the list because it's has the earliest time associated with it.
When that callback finishes executing, the JS interpreter again returns control back to the event loop where it again checks if there isn't anything else to do. It will find that the func1 timer is now at the head of the list and past its time to run so it grabs the callback associated with that timer and executes it.
And thus, you get the output you see with the func2 callback executing as soon as the while spin loop is done, then the func1 callback executing after that.
Note, these timers are purely event driven. There is no interrupting of the currently executing Javascript to execute a timer. For this reason, timers in Javascript are a best effort kind of implementation. If you set a timer for 1000ms from now, then the callback associated with that timer will run no sooner than 1000ms and could be later than that if the JS interpreter was busy at the appointed time for that timer.
The one aspect of timers that is missing from the above description (because it doesn't occur in your situation) is what happens if you don't have the while() spin loop. In that case, your code returns control back to the event loop right after configuring both timers, the event loop checks to see if any timers are ready to run, but none are yet ready to run. It will then sleep until something wakes it up again, but not sleep longer than the time to the next currently set timer.
No, wait. It won't add your timeout call to the event queue. It's handled by the webapi by the browser and then when your timeout kicks-off then it'll add your function to the event queue.
Whatch this: https://www.youtube.com/watch?v=8aGhZQkoFbQ#t=13m
(From 13:00)
Javascript is single-threaded. Even though there are asynchronous callbacks, they are not con-current.
This means, the code inside(setTimeout(fn, num)) only gets called once the entire code has finished execution. Therefore, if num parameter = 5000. This means, the function setTimeout(...) will run: after the entire code (i.e. not just the code up to the point when setTimeout is called but everything) has finished executing + 5 seconds. Hope this helps.
Is there any way to call a function periodically in JavaScript?
The setInterval() method, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. It returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval().
var intervalId = setInterval(function() {
alert("Interval reached every 5s")
}, 5000);
// You can clear a periodic function by uncommenting:
// clearInterval(intervalId);
See more # setInterval() # MDN Web Docs
Please note that setInterval() is often not the best solution for periodic execution - It really depends on what javascript you're actually calling periodically.
eg. If you use setInterval() with a period of 1000ms and in the periodic function you make an ajax call that occasionally takes 2 seconds to return you will be making another ajax call before the first response gets back. This is usually undesirable.
Many libraries have periodic methods that protect against the pitfalls of using setInterval naively such as the Prototype example given by Nelson.
To achieve more robust periodic execution with a function that has a jQuery ajax call in it, consider something like this:
function myPeriodicMethod() {
$.ajax({
url: ...,
success: function(data) {
...
},
complete: function() {
// schedule the next request *only* when the current one is complete:
setTimeout(myPeriodicMethod, 1000);
}
});
}
// schedule the first invocation:
setTimeout(myPeriodicMethod, 1000);
Another approach is to use setTimeout but track elapsed time in a variable and then set the timeout delay on each invocation dynamically to execute a function as close to the desired interval as possible but never faster than you can get responses back.
Everyone has a setTimeout/setInterval solution already. I think that it is important to note that you can pass functions to setInterval, not just strings. Its actually probably a little "safer" to pass real functions instead of strings that will be "evaled" to those functions.
// example 1
function test() {
alert('called');
}
var interval = setInterval(test, 10000);
Or:
// example 2
var counter = 0;
var interval = setInterval(function() { alert("#"+counter++); }, 5000);
Old question but..
I also needed a periodical task runner and wrote TaskTimer. This is also useful when you need to run multiple tasks on different intervals.
// Timer with 1000ms (1 second) base interval resolution.
const timer = new TaskTimer(1000);
// Add task(s) based on tick intervals.
timer.add({
id: 'job1', // unique id of the task
tickInterval: 5, // run every 5 ticks (5 x interval = 5000 ms)
totalRuns: 10, // run 10 times only. (set to 0 for unlimited times)
callback(task) {
// code to be executed on each run
console.log(task.id + ' task has run ' + task.currentRuns + ' times.');
}
});
// Start the timer
timer.start();
TaskTimer works both in browser and Node. See documentation for all features.
You will want to have a look at setInterval() and setTimeout().
Here is a decent tutorial article.
yes - take a look at setInterval and setTimeout for executing code at certain times. setInterval would be the one to use to execute code periodically.
See a demo and answer here for usage
Since you want the function to be executed periodically, use setInterval
function test() {
alert('called!');
}
var id = setInterval('test();', 10000); //call test every 10 seconds.
function stop() { // call this to stop your interval.
clearInterval(id);
}
The native way is indeed setInterval()/clearInterval(), but if you are already using the Prototype library you can take advantage of PeriodicalExecutor:
new PeriodicalUpdator(myEvent, seconds);
This prevents overlapping calls. From http://www.prototypejs.org/api/periodicalExecuter:
"it shields you against multiple parallel executions of the callback function, should it take longer than the given interval to execute (it maintains an internal “running” flag, which is shielded against exceptions in the callback function). This is especially useful if you use one to interact with the user at given intervals (e.g. use a prompt or confirm call): this will avoid multiple message boxes all waiting to be actioned."