`

JavaScript Garden - setTimeout 和 setInterval

阅读更多

setTimeout 和 setInterval

由于 JavaScript 是异步的,可以使用 setTimeout 和 setInterval 来计划执行函数。

注意: 定时处理不是 ECMAScript 的标准,它们在 DOM (文档对象模型) 被实现。

function foo() {}
var id = setTimeout(foo, 1000); // 返回一个大于零的数字

当 setTimeout 被调用时,它会返回一个 ID 标识并且计划在将来大约 1000 毫秒后调用 foo 函数。
foo 函数只会被执行一次

基于 JavaScript 引擎的计时策略,以及本质上的单线程运行方式,所以其它代码的运行可能会阻塞此线程。
因此没法确保函数会在 setTimeout 指定的时刻被调用。

作为第一个参数的函数将会在全局作用域中执行,因此函数内的 this 将会指向这个全局对象。

function Foo() {
    this.value = 42;
    this.method = function() {
        // this 指向全局对象
        console.log(this.value); // 输出:undefined
    };
    setTimeout(this.method, 500);
}
new Foo();

注意: setTimeout 的第一个参数是函数对象,一个常犯的错误是这样的 setTimeout(foo(), 1000)
这里回调函数是 foo 的返回值,而不是foo本身。
大部分情况下,这是一个潜在的错误,因为如果函数返回 undefinedsetTimeout 也不会报错。

setInterval 的堆调用

setTimeout 只会执行回调函数一次,不过 setInterval - 正如名字建议的 - 会每隔 X 毫秒执行函数一次。
但是却不鼓励使用这个函数。

当回调函数的执行被阻塞时,setInterval 仍然会发布更多的毁掉指令。在很小的定时间隔情况下,这会导致回调函数被堆积起来。

function foo(){
    // 阻塞执行 1 秒
}
setInterval(foo, 100);

上面代码中,foo 会执行一次随后被阻塞了一分钟。

在 foo 被阻塞的时候,setInterval 仍然在组织将来对回调函数的调用。
因此,当第一次 foo 函数调用结束时,已经有 10 次函数调用在等待执行。

处理可能的阻塞调用

最简单也是最容易控制的方案,是在回调函数内部使用 setTimeout 函数。

function foo(){
    // 阻塞执行 1 秒
    setTimeout(foo, 100);
}
foo();

这样不仅封装了 setTimeout 回调函数,而且阻止了调用指令的堆积,可以有更多的控制。
foo 函数现在可以控制是否继续执行还是终止执行。

手工清空定时器

可以通过将定时时产生的 ID 标识传递给 clearTimeout 或者 clearInterval 函数来清除定时,
至于使用哪个函数取决于调用的时候使用的是 setTimeout 还是 setInterval

var id = setTimeout(foo, 1000);
clearTimeout(id);

清除所有定时器

由于没有内置的清除所有定时器的方法,可以采用一种暴力的方式来达到这一目的。

// 清空"所有"的定时器
for(var i = 1; i < 1000; i++) {
    clearTimeout(i);
}

可能还有些定时器不会在上面代码中被清除(译者注如果定时器调用时返回的 ID 值大于 1000),
因此我们可以事先保存所有的定时器 ID,然后一把清除。

隐藏使用 eval

setTimeout 和 setInterval 也接受第一个参数为字符串的情况。
这个特性绝对不要使用,因为它在内部使用了 eval

注意: 由于定时器函数不是 ECMAScript 的标准,如何解析字符串参数在不同的 JavaScript 引擎实现中可能不同。
事实上,微软的 JScript 会使用 Function 构造函数来代替 eval 的使用。

function foo() {
    // 将会被调用
}

function bar() {
    function foo() {
        // 不会被调用
    }
    setTimeout('foo()', 1000);
}
bar();

由于 eval 在这种情况下不是被直接调用,因此传递到 setTimeout 的字符串会自全局作用域中执行;
因此,上面的回调函数使用的不是定义在 bar 作用域中的局部变量 foo

建议不要在调用定时器函数时,为了向回调函数传递参数而使用字符串的形式。

function foo(a, b, c) {}

// 不要这样做
setTimeout('foo(1,2, 3)', 1000)

// 可以使用匿名函数完成相同功能
setTimeout(function() {
    foo(a, b, c);
}, 1000)

注意: 虽然也可以使用这样的语法 setTimeout(foo, 1000, a, b, c)
但是不推荐这么做,因为在使用对象的属性方法时可能会出错。
译者注:这里说的是属性方法内,this 的指向错误)

结论

绝对不要使用字符串作为 setTimeout 或者 setInterval 的第一个参数,
这么写的代码明显质量很差。当需要向回调函数传递参数时,可以创建一个匿名函数,在函数内执行真实的回调函数。

另外,应该避免使用 setInterval,因为它的定时执行不会被 JavaScript 阻塞。

分享到:
评论

相关推荐

    JavaScript_Garden_CN

    6. **其他**: 提及了`setTimeout`和`setInterval`的使用,以及它们在异步编程中的角色。 #### 对象的深度解析 - **对象的创建与使用**: 在JavaScript中,对象可以被看作是哈希表,用于存储键值对。使用字面量语法`...

    COMSOL激光增材制造技术:热流力三场耦合模型的构建与模拟研究,COMSOL激光增材制造中热-流-力三场耦合模型的研究与应用:基于固体传热、固体力学、层流和动网格技术的多物理场分析,comsol激光

    COMSOL激光增材制造技术:热流力三场耦合模型的构建与模拟研究,COMSOL激光增材制造中热-流-力三场耦合模型的研究与应用:基于固体传热、固体力学、层流和动网格技术的多物理场分析,comsol激光增材制造热-流-力三场偶合模型 选用固体传热,固体力学,层流和动网格,考虑热物性以及马兰戈尼效应、表面张力,相变潜热,热对流和热辐射等 【软件工具】COMSOL5.6 【备注】,comsol三维模型 ,核心关键词:comsol; 激光增材制造; 热-流-力三场偶合模型; 固体传热; 固体力学; 层流; 动网格; 热物性; 马兰戈尼效应; 表面张力; 相变潜热; 热对流; 热辐射; COMSOL5.6; 三维模型。,COMSOL 5.6激光增材制造三场耦合模型

    基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SMO的对比:有效消除转速抖动,基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SM

    基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SMO的对比:有效消除转速抖动,基于PLL的SMO滑模观测器算法在永磁同步电机无传感器矢量控制中的应用及其与反正切SMO的对比:有效消除转速抖动,基于PLL的SMO滑模观测器算法,永磁同步电机无传感器矢量控制,跟基于反正切的SMO做对比,可以有效消除转速的抖动。 ,基于PLL的SMO滑模观测器算法; 永磁同步电机无传感器矢量控制; 反正切SMO; 转速抖动消除。,基于PLL SMO滑模观测器:永磁同步电机无传感器矢量控制新算法,优化抖动消除效能

    【毕业设计】java-springboot+vue个人云盘管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue个人云盘管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    【语音识别】基于matlab自适应滤波器LMS算法鸟类物种识别【含Matlab源码 9977期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【毕业设计】java-springboot-vue电影推荐系统实现源码(完整前后端-mysql-说明文档-LunW).zip

    【毕业设计】java-springboot-vue电影推荐系统实现源码(完整前后端-mysql-说明文档-LunW).zip

    基于OpenCV和Python的实时口罩识别系统:支持摄像头与图片检测,界面简洁操作便捷,基于OpenCV的口罩识别系统 相关技.

    基于OpenCV和Python的实时口罩识别系统:支持摄像头与图片检测,界面简洁操作便捷,基于OpenCV的口罩识别系统 相关技术:python,opencv,pyqt (请自行安装向日葵远程软件,以便提供远程帮助) 软件说明:读取用户设备的摄像头,可实时检测画面中的人的口罩佩戴情况,并给予提示。 有基础的同学,可稍作修改,检测图片。 第一张为运行主界面。 第二张为部分代码截图。 第三和第四张为运行界面。 ,基于OpenCV的口罩识别系统; Python; OpenCV; PyQt; 远程协助; 摄像头读取; 实时检测; 口罩佩戴情况提示; 代码截图; 运行界面。,"基于OpenCV与Python的口罩识别系统:实时检测与提醒"

    Git与GitHub入门指南:版本控制、协作开发及基础命令教程

    内容概要:本文是一份关于 Git 和 GitHub 的入门指南,详细介绍了一整套从安装到进阶使用的完整流程。文章首先阐述了版本控制的重要性,并解释了 Git 的特点和优势。接着逐步介绍了 Git 和 GitHub 的使用方法,包括安装设置 Git、创建和管理 GitHub 账户、创建和克隆仓库,以及日常操作如提交、推送、拉取、分支管理和处理冲突的具体指令和操作步骤。还涉及到高级主题如合并请求、持续集成等功能的介绍,帮助读者深入了解 Git 和 GitHub 的应用范围和最佳实践。 适用人群:适用于刚开始接触版本控制系统的初学者,特别是那些正在寻找 Git 和 GitHub 实际操作指导的学生和技术爱好者。 使用场景及目标:①为刚踏入软件开发领域的新人提供详尽的基础教学,使其能够快速理解和掌握必要的技能;②指导已有一定经验但仍想进一步深化理解的开发人员如何优化日常工作流程;③促进团队合作效率提升,通过具体的实例演示如何利用版本控制系统协调多人协作。 其他说明:随着 Git 和 GitHub 成为现代软件开发的标准工具之一,这份资料不仅涵盖了关键知识点,而且配有多图例解析和实操练习,确保每个阶段的学习都能得到良好反馈和支持。读者可以通过动手实践来巩固所学知识,在实践中遇到困难也能及时参考本文获得解决方案。

    python安装-16. 使用指定序列和数值创建一个字典-分配伴侣.py

    python安装-16. 使用指定序列和数值创建一个字典——分配伴侣.py

    Python+OpenCV魔方识别系

    本研究的目的是基于Python和OpenCV开发一个魔方识别系统,并提供相应的源码和部署教程。通过该系统,用户可以将魔方的图像输入,系统可以自动识别魔方的状态,并给出相应的还原方案。具体来说,本研究的主要内容包括以下几个方面: 图像预处理:通过使用OpenCV提供的图像处理算法,对输入的魔方图像进行预处理,包括图像去噪、边缘检测、图像分割等操作,以提高后续的识别准确率。 特征提取与模式识别:通过使用OpenCV提供的特征提取算法,对预处理后的图像进行特征提取,以获取魔方的状态信息。然后,通过机器学习算法,对提取到的特征进行模式识别,以确定魔方的状态。 还原方案生成:根据识别到的魔方状态,使用经典的还原算法,生成相应的还原方案。通过该方案,用户可以轻松地还原魔方,提高解决效率。

    基于Springboot与Vue.js的WMS仓库管理系统源码详解:前后端分离架构下的Java实践与功能详述,基于Springboot和Vue的前后端分离WMS仓库管理系统源码,详细功能参考详情 ,S

    基于Springboot与Vue.js的WMS仓库管理系统源码详解:前后端分离架构下的Java实践与功能详述,基于Springboot和Vue的前后端分离WMS仓库管理系统源码,详细功能参考详情。,Springboot vue仓库管理系统源码Java 前后端分离 WMS仓库管理 BS 功能见详情 ,Springboot; Vue; 仓库管理系统; 源码; Java; 前后端分离; WMS仓库管理; BS; 功能详情,Springboot+Vue仓库管理系统源码:前后端分离的WMS管理BS应用

    用AI学安卓游戏开发1-控制小球上下左右移动2代码

    用AI学安卓游戏开发1——控制小球上下左右移动2代码, 初始化小球随机自有移动,遇到屏幕边缘反弹,摇杆介入后小球停止自有移动,按照摇杆控制方向移动。

    【图像融合】基于matlab拉普拉斯方法水下图像增强融合【含Matlab源码 9983期】复现.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【图像加密】基于matlab差分扩展缩略图保持加密【含Matlab源码 9692期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【图像重建】CT图像重建【含Matlab源码 8035期】.md

    CSDN Matlab武动乾坤上传的资料均是完整代码运行出的仿真结果图,可见完整代码亲测可用,适合小白; 1、完整的代码内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描博客文章底部QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,110kV海底电缆-架空线雷击过电压ATP-EMTP

    基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,基于ATP-EMTP的110kV海底电缆与架空线雷击过电压仿真分析与研究,110kV海底电缆-架空线雷击过电压ATP-EMTP仿真分析 ,核心关键词: 110kV海底电缆; 架空线; 雷击过电压; ATP-EMTP仿真分析; 分析。 关键词用分号分隔,如上所示。,雷击过电压仿真分析:110kV海底电缆及架空线ATP-EMTP研究

    基于800kV高压直流输电的VSC-HVDC仿真模型研究:控制策略与性能分析,基于800kV-VSC-HVDC的直流输电仿真模型研究:深入探讨控制结构与电压稳定性,800kV-VSC-HVDC直流输电

    基于800kV高压直流输电的VSC-HVDC仿真模型研究:控制策略与性能分析,基于800kV-VSC-HVDC的直流输电仿真模型研究:深入探讨控制结构与电压稳定性,800kV-VSC-HVDC直流输电仿真模型(Matlab) 流器拓扑:VSC两电平流器 电压等级:直流800kV,交流500kV 控制结构:逆变侧定有功控制与电流内环PI+前馈解耦,整流侧定直流电压与电流内环+PI前馈解耦; 输电距离:100km; 双端电压电流均为对称的三相电压电流; 直流电压稳定在800kV; 双端网侧THD<2% 电子资料, ,800kV; VSC HVDC; 直流输电仿真模型; Matlab; VSC两电平换流器; 直流电压稳定; 逆变侧定有功控制; 电流内环PI+前馈解耦; 整流侧定直流电压与电流内环; 输电距离; 双端电压电流对称; 双端网侧THD<2%。,Matlab仿真模型:800kV VSC两电平换流器HVDC输电系统

    【电池】基于matlab太阳能电池漂移扩散【含Matlab源码 11051期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【毕业设计】java-springboot-vue电商应用系统实现源码(完整前后端-mysql-说明文档-LunW).zip

    【毕业设计】java-springboot-vue电商应用系统实现源码(完整前后端-mysql-说明文档-LunW).zip

    【运动学】基于matlab追踪法导弹打飞机仿真【含Matlab源码 11016期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

Global site tag (gtag.js) - Google Analytics