📜  解释 JavaScript 中定时器的工作原理

📅  最后修改于: 2022-05-13 01:56:15.847000             🧑  作者: Mango

解释 JavaScript 中定时器的工作原理

在本文中,我们将详细讨论 JavaScript 中计时器的工作原理

众所周知,JavaScript 是一种异步和单线程的编程语言。这意味着只有一个调用堆栈,并且在调用堆栈中的代码被一一执行。

同步意味着代码被一一执行,单线程意味着我们只有一个调用堆栈的主线程。但我们也可以实现异步功能。

计时器用于在特定时间间隔后执行某些任务。基本上,借助 JavaScript 中的计时器,我们可以延迟代码执行。借助 JavaScript 中的计时器函数,我们也可以实现异步功能。

假设我们在定时器函数的帮助下延迟了某个函数的执行,那么当 JavaScript 引擎遇到它时,该函数将不会被执行。它将存储在其他地方,当计时器到期时,将执行该函数。

JavaScript 提供了两个函数来延迟任务的执行。这些是定时器功能。

  • 设置超时函数
  • setInterval函数

JavaScript 中定时器的工作:现在让我们讨论定时器函数是如何实际运行的。

我们将通过一个例子来理解它。

例子:

Javascript
function print() {
    console.log("Welcome to GFG");
}
setTimeout(print, 5000);
console.log("Hello World!");


Javascript
function print() {
    for(let i = 0; i <= 5; i++) {
        setTimeout(() => {
            console.log(i);
        }, 2000);
    }
}
print();


Javascript
var count = 1;
function print() {
    console.log(count);
    count++;
}
setInterval(print, 2000);


Javascript
var count = 1;
function print() {
    console.log(count);
    count++;
    if(count == 6) {
        clearInterval(id);
    }
}
  
let id = setInterval(print, 2000);


Javascript
function sayHello() {
    console.log("Hello world!");
}
function stopTimer() {
    clearTimeout(id);
}
const id = setTimeout(sayHello, 2000);
console.log("This should be executed first");
stopTimer();


Javascript
var count = 1;
function sayHelloWorld() {
    console.log("Hello World!");
    count = count+1;
    if(count == 6) {
        clearInterval(id);
    }
}
let id = setInterval(sayHelloWorld, 2000);


输出:

Hello World!
Welcome to GFG

说明:在这种情况下,非常有趣的是首先执行 console.log(“Hello World!”),然后执行 setTimout。当我们第一次运行任何代码时,会创建一个全局执行上下文的原因。并推入调用堆栈。因此,当遇到 setTimout() 时,它不会被直接推送到调用堆栈中。它将存储在 WebAPIs 环境中。

因为 setTimout()函数不是 JavaScript 的一部分,所以它是浏览器提供的用于与外部环境交互的 API。所以 setTimeout 是 Web 浏览器的一部分,而不是 JavaScript 的一部分。

当 JavaScript 引擎遇到 setTimeout 时,它将被存储在 WebAPIs 环境中,并且 JS 引擎将继续执行下一行代码。所以console.log(“Hello World!)首先被执行。由于我们已经在全局范围内执行了所有内容,因此全局执行上下文将从调用堆栈中出来。

当 5 秒的计时器到期时,setTimeout 将进入任务队列。

然后事件循环开始发挥作用,事件循环不断检查我们的调用堆栈是否为空。如果调用堆栈为空,并且我们在任务队列中有一个要执行的函数,那么它将获取该函数并将其推送到调用堆栈中。因为在我们的例子中,我们已经在全局范围内执行了所有操作,所以它会从调用堆栈中弹出,并且我们的调用堆栈是空的,并且在任务队列中执行了一个函数。

因此事件循环将从任务队列中获取该函数并将其推送到调用堆栈中。结果“Welcome to GFG”将在 5 秒后打印。

setTimeout()函数:是浏览器提供的与外界交互的API。它只会在我们完成执行全局范围内的所有内容后才会执行,然后它将被推入调用堆栈并因此执行。

例子:

Javascript

function print() {
    for(let i = 0; i <= 5; i++) {
        setTimeout(() => {
            console.log(i);
        }, 2000);
    }
}
print();

输出:

0
1
2
3
4
5

setInterval()函数:用于在给定时间段后重复执行该函数。我们需要停止这个函数,否则,它将继续执行它。

例子:

Javascript

var count = 1;
function print() {
    console.log(count);
    count++;
}
setInterval(print, 2000);

在这种情况下,它将继续打印 i 的值。它不会停下来。我们需要使用clearInterval()函数明确地停止它。

停止 setInterval函数:

Javascript

var count = 1;
function print() {
    console.log(count);
    count++;
    if(count == 6) {
        clearInterval(id);
    }
}
  
let id = setInterval(print, 2000);

输出:

1
2
3
4
5

clearTimeout()函数:用于停止setTimeout函数。就像 clearInterval( )函数用于停止 setInterval函数一样,我们可以使用 clearTimeout函数取消 setTimeout函数的执行。

Javascript

function sayHello() {
    console.log("Hello world!");
}
function stopTimer() {
    clearTimeout(id);
}
const id = setTimeout(sayHello, 2000);
console.log("This should be executed first");
stopTimer();

输出:

This should be executed first

clearTimeout()函数已停止执行 setTimeout()函数。

clearInterval函数:众所周知,setInterval函数会在特定的时间间隔后继续执行该函数。我们需要阻止它。要停止 setInterval函数,我们使用 clearInterval函数。

例子:

Javascript

var count = 1;
function sayHelloWorld() {
    console.log("Hello World!");
    count = count+1;
    if(count == 6) {
        clearInterval(id);
    }
}
let id = setInterval(sayHelloWorld, 2000);

输出:

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!