JS【详解】setTimeout 延时(含扫除 setTimeout,计时开始时间,0 秒延时解 ...

打印 上一主题 下一主题

主题 878|帖子 878|积分 2634

setTimeout 简介

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


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

  1. clearTimeout(timer); // timer 为计时器的ID
复制代码
  setTimeout 什么时候开始计时?

  实行到 setTimeout 时,因其为宏任务,会将其放入 Web APIs 中,并开始计时
   0 秒延时并不代表立即实行!

  

如上图可见,属于 宏任务的 setTimeout 需等候同步任务、微任务、DOM渲染完成后,通过事件轮询触发实行
  1. print("同步任务执行开始");
  2. setTimeout(function () {
  3.   print("setTimeout延时0秒执行");
  4. }, 0);
  5. print("同步任务执行结束");
复制代码
实行效果
  1. 同步任务执行开始————当前时间:2024年5月29日14时42分29秒
  2. 同步任务执行结束————当前时间:2024年5月29日14时42分29秒
  3. setTimeout延时0秒执行————当前时间:2024年5月29日14时42分29秒
复制代码
  setTimeout 的回调函数,详细什么时候开始实行?

  存在复杂异步逻辑时,很难精准预判 setTimeout 的回调函数的开始实行时间。
逻辑简朴的,比力好分析,如
  1. function print(info) {
  2.   let dt = new Date();
  3.   var y = dt.getFullYear();
  4.   var mt = dt.getMonth() + 1;
  5.   var day = dt.getDate();
  6.   var h = dt.getHours(); //获取时
  7.   var m = dt.getMinutes(); //获取分
  8.   var s = dt.getSeconds(); //获取秒
  9.   let str =
  10.     "当前时间:" +
  11.     y +
  12.     "年" +
  13.     mt +
  14.     "月" +
  15.     day +
  16.     "日" +
  17.     h +
  18.     "时" +
  19.     m +
  20.     "分" +
  21.     s +
  22.     "秒";
  23.   console.log(info + "————" + str);
  24. }
  25. function sleep(delay) {
  26.   var start = new Date().getTime();
  27.   while (new Date().getTime() - start < delay) {
  28.     continue;
  29.   }
  30.   print("sleep 执行完毕");
  31. }
  32. function test() {
  33.   print("开始");
  34.   sleep(1000);
  35.   setTimeout(() => {
  36.     print("执行 setTimeout");
  37.   }, 1000);
  38.   print("结束");
  39. }
  40. test();
复制代码
实行效果
  1. 开始————当前时间:2024年5月29日14时11分23秒
  2. sleep 执行完毕————当前时间:2024年5月29日14时11分24秒
  3. 结束————当前时间:2024年5月29日14时11分24秒
  4. 执行 setTimeout————当前时间:2024年5月29日14时11分25秒
复制代码
  多个 setTimeout 的实行顺序 ?

  1. function test() {
  2.   console.time("本段代码总耗时");
  3.   print("同步任务执行开始");
  4.   setTimeout(function () {
  5.     print("setTimeout延时3秒执行");
  6.     console.timeEnd("本段代码总耗时");
  7.   }, 3000);
  8.   setTimeout(function () {
  9.     print("第1个setTimeout延时2秒执行");
  10.   }, 2000);
  11.   setTimeout(function () {
  12.     print("第2个setTimeout延时2秒执行");
  13.   }, 2000);
  14.   print("同步任务执行结束");
  15. }
  16. test();
复制代码
实行效果
  1. 同步任务执行开始————当前时间:2024年5月29日14时21分20秒
  2. 同步任务执行结束————当前时间:2024年5月29日14时21分20秒
  3. 第1个setTimeout延时2秒执行————当前时间:2024年5月29日14时21分22秒
  4. 第2个setTimeout延时2秒执行————当前时间:2024年5月29日14时21分22秒
  5. setTimeout延时3秒执行————当前时间:2024年5月29日14时21分23秒
  6. 本段代码总耗时: 3.005s
复制代码


  • 所有 setTimeout 的开始计时时间几乎相同
  • 延时相同的 setTimeout ,会按 setTimeout 的出现的先后顺序实行
  • 延时差别的 setTimeout ,延时越久的 setTimeout 越晚实行
   setTimeout 的应用场景

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

  1. window.onload = function () {
  2.     //获取相关元素
  3.     var imgArr = document.getElementsByTagName("img");
  4.     //设置定时器:5秒后关闭两侧的广告栏
  5.     setTimeout(fn,5000);
  6.     function fn(){
  7.         imgArr[0].style.display = "none";
  8.         imgArr[1].style.display = "none";
  9.     }
  10. }
复制代码
  setTimeout 的网红口试题

  下方代码的实行效果是?

  1. for (var i = 0; i < 10; i++) {
  2.   setTimeout(() => {
  3.     console.log(i);
  4.   });
  5. }
复制代码
答案
  1. 10
  2. 10
  3. 10
  4. 10
  5. 10
  6. 10
  7. 10
  8. 10
  9. 10
  10. 10
复制代码
解析 :
setTimeout 是异步宏任务,for 循环是同步任务,for 循环先实行,依次在Web APIs 中添加了10个setTimeout,待 for 循环完毕,i 的值已变为 10 ,此时才开始事件轮询,setTimeout 依次开始计时,因延时为0秒,最终效果为 for 循环完毕后,立马一次实行 10 次 setTimeout 的回调,即依次打印 10 个 10
延展提问:怎样改动实现打印 0 到 9 ?

答案1:将 var 改成 let

  1. for (let i = 0; i < 10; i++) {
  2.   setTimeout(() => {
  3.     console.log(i);
  4.   });
  5. }
复制代码
解析:let 声明的变量具有局部作用域, var 声明的变量是全局作用域,改用 let 后,实行 setTimeout 内的回调函数时,取到的 i 值为 setTimeout 被放入 Web APIs 时的值,即 for 循环时 i 的值。
答案2:改用立即实行函数包裹

  1. for (var i = 0; i < 10; i++) {
  2.   (function (i) {
  3.     setTimeout(() => {
  4.       console.log(i);
  5.     });
  6.   })(i);
  7. }
复制代码
解析:立即实行函数的原理和 let 类似,也是形成了局部作用域,实现了预期效果。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美丽的神话

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表