当前位置:首页 » 《随便一记》 » 正文

JS【详解】setTimeout 延时(含清除 setTimeout,计时开始时间,0 秒延时解析,多 setTimeout 执行顺序,setTimeout 应用场景,网红面试题)

6 人参与  2024年12月11日 12:00  分类 : 《随便一记》  评论

点击全文阅读


setTimeout 简介

setTimeout 是一个 js 内置的函数,用于延时执行代码

参数1:回调函数,延迟一段时间后执行的代码参数2:延迟的时间,单位是毫秒。(默认为 0 毫秒)返回值:计时器的ID,是一个整数(例子中的 timer)。
const timer = setTimeout(function() {    console.log(1); // 3 秒后,打印 1}, 3000);

清除 setTimeout

clearTimeout(timer); // timer 为计时器的ID

setTimeout 什么时候开始计时?

执行到 setTimeout 时,因其为宏任务,会将其放入 Web APIs 中,并开始计时

0 秒延时并不代表立即执行!

在这里插入图片描述
如上图可见,属于 宏任务的 setTimeout 需等待同步任务、微任务、DOM渲染完成后,通过事件轮询触发执行

print("同步任务执行开始");setTimeout(function () {  print("setTimeout延时0秒执行");}, 0);print("同步任务执行结束");

执行结果

同步任务执行开始————当前时间:2024年5月29日14时42分29秒同步任务执行结束————当前时间:2024年5月29日14时42分29秒setTimeout延时0秒执行————当前时间:2024年5月29日14时42分29秒

setTimeout 的回调函数,具体什么时候开始执行?

存在复杂异步逻辑时,很难精准预判 setTimeout 的回调函数的开始执行时间。

逻辑简单的,比较好分析,如

function print(info) {  let dt = new Date();  var y = dt.getFullYear();  var mt = dt.getMonth() + 1;  var day = dt.getDate();  var h = dt.getHours(); //获取时  var m = dt.getMinutes(); //获取分  var s = dt.getSeconds(); //获取秒  let str =    "当前时间:" +    y +    "年" +    mt +    "月" +    day +    "日" +    h +    "时" +    m +    "分" +    s +    "秒";  console.log(info + "————" + str);}function sleep(delay) {  var start = new Date().getTime();  while (new Date().getTime() - start < delay) {    continue;  }  print("sleep 执行完毕");}function test() {  print("开始");  sleep(1000);  setTimeout(() => {    print("执行 setTimeout");  }, 1000);  print("结束");}test();

执行结果

开始————当前时间:2024年5月29日14时11分23秒sleep 执行完毕————当前时间:2024年5月29日14时11分24秒结束————当前时间:2024年5月29日14时11分24秒执行 setTimeout————当前时间:2024年5月29日14时11分25秒

多个 setTimeout 的执行顺序 ?

function test() {  console.time("本段代码总耗时");  print("同步任务执行开始");  setTimeout(function () {    print("setTimeout延时3秒执行");    console.timeEnd("本段代码总耗时");  }, 3000);  setTimeout(function () {    print("第1个setTimeout延时2秒执行");  }, 2000);  setTimeout(function () {    print("第2个setTimeout延时2秒执行");  }, 2000);  print("同步任务执行结束");}test();

执行结果

同步任务执行开始————当前时间:2024年5月29日14时21分20秒同步任务执行结束————当前时间:2024年5月29日14时21分20秒第1个setTimeout延时2秒执行————当前时间:2024年5月29日14时21分22秒第2个setTimeout延时2秒执行————当前时间:2024年5月29日14时21分22秒setTimeout延时3秒执行————当前时间:2024年5月29日14时21分23秒本段代码总耗时: 3.005s
所有 setTimeout 的开始计时时间几乎相同延时相同的 setTimeout ,会按 setTimeout 的出现的先后顺序执行延时不同的 setTimeout ,延时越久的 setTimeout 越晚执行

setTimeout 的应用场景

5秒后关闭网页两侧的广告栏

window.onload = function () {    //获取相关元素    var imgArr = document.getElementsByTagName("img");    //设置定时器:5秒后关闭两侧的广告栏    setTimeout(fn,5000);    function fn(){        imgArr[0].style.display = "none";        imgArr[1].style.display = "none";    }}

setTimeout 的网红面试题

下方代码的执行结果是?

for (var i = 0; i < 10; i++) {  setTimeout(() => {    console.log(i);  });}

答案

10101010101010101010

解析 :

setTimeout 是异步宏任务,for 循环是同步任务,for 循环先执行,依次在Web APIs 中添加了10个setTimeout,待 for 循环完毕,i 的值已变为 10 ,此时才开始事件轮询,setTimeout 依次开始计时,因延时为0秒,最终效果为 for 循环完毕后,立马一次执行 10 次 setTimeout 的回调,即依次打印 10 个 10

延展提问:怎样改动实现打印 0 到 9 ?

答案1:将 var 改成 let

for (let i = 0; i < 10; i++) {  setTimeout(() => {    console.log(i);  });}

解析:let 声明的变量具有局部作用域, var 声明的变量是全局作用域,改用 let 后,执行 setTimeout 内的回调函数时,取到的 i 值为 setTimeout 被放入 Web APIs 时的值,即 for 循环时 i 的值。

答案2:改用立即执行函数包裹

for (var i = 0; i < 10; i++) {  (function (i) {    setTimeout(() => {      console.log(i);    });  })(i);}

解析:立即执行函数的原理和 let 类似,也是形成了局部作用域,实现了预期效果。


点击全文阅读


本文链接:http://zhangshiyu.com/post/199518.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1