This is the 13th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021.
Since JavaScript is asynchronous, you can use setTimeout and setInterval to plan the execution of functions.
Note: timed processing is not an ECMAScript standard; it is implemented in the DOM.
function foo() {}
var id = setTimeout(foo, 1000); // Return a number greater than zero
Copy the code
When setTimeout is called, it returns an ID and plans to call foo in the future in about 1000 milliseconds. Foo is executed only once.
Based on the timing strategy of the JavaScript engine, and the nature of the single-threaded execution, other code execution may block this thread. There is therefore no guarantee that the function will be called at the time specified by setTimeout.
The function that takes the first argument will be executed in the global scope, so this inside the function will refer to the global object.
function Foo() {
this.value = 42;
this.method = function() {
// This points to the global object
console.log(this.value); // output: undefined
};
setTimeout(this.method, 500);
}
new Foo();
Copy the code
Note: The first argument to setTimeout is a function object. A common mistake is to call setTimeout(foo(), 1000), where the callback function is the return value of foo, not foo itself. In most cases, this is a potential error, because setTimeout will not fail if the function returns undefined.
The heap call to setInterval
SetTimeout only executes the callback once, but setInterval – as the name suggests – executes the function once every X milliseconds. However, the use of this function is discouraged.
When the execution of the callback function is blocked, setInterval still issues more callbacks. This can cause callbacks to pile up at very small timing intervals.
function foo(){
// Block execution for 1 second
}
setInterval(foo, 100);
Copy the code
In the code above, Foo executes once and then blocks for a second.
While foo is blocked, setInterval still organizes future calls to the callback function. So, by the time the first foo call ends, there are 10 function calls waiting to be executed.
Handle possible blocking calls
The simplest and most manageable solution is to use the setTimeout function inside the callback function.
function foo(){
// Block execution for 1 second
setTimeout(foo, 100);
}
foo();
Copy the code
This not only encapsulates the setTimeout callback function, but also prevents the accumulation of calling instructions, allowing for more control. The foo function now controls whether execution continues or terminates.
Manual emptying timer
Timing can be cleared by passing the ID generated during timing to clearTimeout or clearInterval functions, depending on whether setTimeout or setInterval is used when the call is made.
var id = setTimeout(foo, 1000);
clearTimeout(id);
Copy the code
Clear all timers
Since there is no built-in way to clear all timers, this can be done in a violent way.
// Clear the "all" timer
for(var i = 1; i < 1000; i++) {
clearTimeout(i);
}
Copy the code
There may be timers that are not cleared in the code above (if the timer call returns an ID greater than 100, so we can save all the timer ids in advance and clear them at once).
Hide using eval
SetTimeout and setInterval also accept the first argument as a string. This feature should never be used because it uses eval internally.
Note: Since the timer function is not an ECMAScript standard, how string parameters are parsed may differ in different JavaScript engine implementations. In fact, Microsoft’s JScript uses the Function constructor instead of using eval.
function foo() {
// will be called
}
function bar() {
function foo() {
// will not be called
}
setTimeout('foo()'.1000);
}
bar();
Copy the code
Since eval is not called directly in this case, the string passed to setTimeout is executed from the global scope; Therefore, the above callback function does not use the local variable foo defined in bar scope.
It is recommended not to use strings to pass arguments to callback functions when calling timer functions.
function foo(a, b, c) {}
// Don't do that
setTimeout('foo (1, 2, 3)'.1000)
// You can use anonymous functions to do the same thing
setTimeout(function() {
foo(1.2.3);
}, 1000)
Copy the code
Note: While it is possible to use the syntax setTimeout(foo, 1000, 1, 2, 3), it is not recommended because of the potential for errors when using object property methods.
conclusion
Never use a string as the first argument to a setTimeout or setInterval. This is obviously bad code. When you need to pass parameters to a callback function, you can create an anonymous function that executes the actual callback function within the function.
Also, you should avoid using setInterval because its timed execution is not blocked by JavaScript.