JavaScript中定时器问题与解决方法

最近在做用setInterval在做定时器的时候,发现一些问题。

就是一旦定时器中一旦任务执行时间超过定时间隔时间得时候,JavaScript不会等待这次任务执行完毕,重现计算时间间隔,而是到时间间隔一到立马将下次任务加入队列,并且等待该次任务执行完毕后,立马执行,所有定时加载变成循环加载。这是我们所不愿意见到的。

setInterval代码:

function startFn2() {
       var p2 = new AlarmClockByInterval(callBackByTest, 2000);
}
function callBackByTest() {
    var i = 0;
    for (; i < 900000000; i++) {

    }
    return true;
}
function AlarmClockByInterval(_args1, _args2) {
    var timeFn, self = this,
        callBackFn = _args1,
        ms = _args2,
        i = 0;
    this.getInterval = function() {
        if (ms) {
            if (!timeFn) {
                timeFn = setInterval(function() {

                    console.log("定时任务开始执行:"+new Date().getTime());
                    callBackFn();
                    console.log("定时任务结束执行:"+new Date().getTime());
                    
                }, ms);
            }
        } else {
            closeInterval();
        }

    }
    this.closeInterval = function() {
        if (timeFn) {
            clearInterval(timeFn);
        }
    }
    self.getInterval();

}

大家可以看到,定时任务一旦执行完毕,立马进行下一次任务,并没有理想中的间隔。

任务执行时间也被计算到间隔时间了。直接用setInterval并不能获得我们理想中的效果。

解决:

使用setTimeOut,和递归,利用函数自动调用自身,很延时执行就可以很好的解决这个问题。

function AlarmClockByTimeOut(_args1, _args2) {
    var _type = 0,
        timeFn, _flag = true,
        ms = _args2,
        callBackFn = _args1,
        self = this;
    this.getTimeOut = function() {
        var _callee = arguments.callee;
        if (_flag) { //内部错误,内部强制中断,终止递归
            if (_type == 0) { //外部终止递归
                timeFn = setTimeout(function() {
                    console.log("定时任务开始执行:"+new Date().getTime());
                    _flag = callBackFn();
                    console.log("定时任务结束执行:"+new Date().getTime());
                    _callee();
                }, ms);
            } else {
                if (timeFn) clearTimeout(timeFn);
                console.error(500, "定时器已终止,外部终止...");
            }
        } else {
            if (timeFn) clearTimeout(timeFn);
            console.error(500, "定时器已终止,回调函数出现错误或内部强制终止...");
        }
    };
    this.close = function(_args1) {
        _type = _args1 || 1;
    };
    self.getTimeOut();
}
function startFn2() {
    var p1 = new AlarmClockByTimeOut(callBackByTest,1000);

    // var p2 = new AlarmClockByInterval(callBackByTest, 2000);
}

执行效果:

这样每次执行完成都会等1000ms,才去加载下一次任务。第一次写博客,有啥问题欢迎讨论

时间: 2024-10-21 03:56:02

JavaScript中定时器问题与解决方法的相关文章

在JavaScript中重写jQuery对象的方法

jQuery是一个很好的类库,它给我们解决了很多的客户端编程,任何东西都不是万能的,当它不能满足我们的需求时我们需要对它进行重写,同时也不要影响其原有的功能或者修改其原有的功能:我现在的web应用程序大多数时候的数据交互都是通过Ajax来完成的,这样就可以将一些隐藏字段的数据保存在HTML标签的属性中,使HTML标签的代码量减少,如:ID,Timestamp等等,这些不需要用户输入但又不得不提交的字段,通过表单提交的做法是 <input name="ID" value="

项目记录:spring+springmvc 项目中 @Transactional 失效的解决方法

第一步,修改spring的配置文件和springmvc的配置文件 --------------------------------applicationContext.xml <context:annotation-config/>  <context:component-scan base-package="com.xxx"> <context:exclude-filter type="annotation" expression=&

CUDA程序编译过程中产生警告的解决方法

有时候经常使用别人用Tabhost+其它的实现demo.单纯利用Tabhost该如何使用呢? 下面看例子: public class MainActivity extends TabActivity { public TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 获取对象 tabHost = getTabH

Ubuntu 14.04中root 密码忘记解决方法[转载+17.04亲测可用]

Ubuntu 14.04中root 密码忘记解决方法 Ubuntu 14.04中root 密码忘记解决方法 方法一: 如果用户具有sudo权限,那么直接可以运行如下命令: #sudo su root #passwd #更改密码 或者直接运行sudo passwd root命令就可以直接更改root密码. 有关sudo su的区别: 1.共同点:都是root用户的权限: 2.不同点:su仅仅取得root权限,工作环境不变,还是在切换之前用户的工作环境:sudo是完全取得root的权限和root的工

phpcms v9 中 PHPSSO无法通讯解决方法(PHPSSO无法通讯间接影响phpcms v9注册会员无法通过“重名无法通过”)

问题的由来 怎么样使用 Cocos2d-x 快速开发游戏,方法很简单,你可以看看其自带的例程,或者从网上搜索教程,运行起第一个HelloWorld,然后在 HelloWorld 里面写相关逻辑代码,添加我们的层.精灵等 ~ 我们并不一定需要知道 Cocos2d-x 是如何运行或者在各种平台之上运行,也不用知道 Cocos2d-x 的游戏是如何运行起来的,它又是如何渲染界面的 ~~~ 两个入口 程序入口的概念是相对的,AppDelegate 作为跨平台程序入口,在这之上做了另一层的封装,封装了不同

Mac 下 Terminal 中 Java乱码的解决方法

在 .bash_profile 中增加一行 export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 就可以了. Mac 下 Terminal 中 Java乱码的解决方法,布布扣,bubuko.com

Javascript中call方法和apply方法用法和区别

第一次在博客园上面写博客,知识因为看书的时候发现了一些有意思的知识,顺便查了一下资料,就发到博客上来了,希望对大家有点帮助. 连续几天阅读<javascript高级程序设计>这本书了,逐渐发现了以前很多自己完全没有用过甚至见过的神奇知识点.今天在阅读到有关函数的属性和方法的时候,略感高级,于是乎,查阅了不少他人的博客,在此总结一下这两个方法的以下几个方面: 1.call()和apply()的作用和用法 2.什么时候用apply(),什么时候用call() 书上提到,每个函数都包含两个非继承而来

PowerShell因为在此系统中禁止执行脚本解决方法

PowerShell因为在此系统中禁止执行脚本解决方法 在Powershell直接脚本时会出现: 无法加载文件 ******.ps1,因为在此系统中禁止执行脚本.有关详细信息,请参阅 "get-help about_signing". 所在位置 行:1 字符: 17 + E:\Test\test.ps1 <<<<     + CategoryInfo          : NotSpecified: (:) [], PSSecurityException    

【转】eclipse中window-&gt;preference选项中没有tomcat的解决方法

eclipse中window->preference选项中没有tomcat的解决方法 2011-09-09 13:46:35|  分类: eclipse|字号 订阅 其实一共有好几种方法,这只是其中的一种:建立link文件法 将下载的tomcat包解压缩到任何你能找到的目录中,也可以解压缩到eclipse下的plugins文件夹下,然后在eclipse目录下建立links文件夹,记住是links,不是link,不要把s掉了,建立好后,在该文件夹下新建一个文件,因为这里是tomcat插件,所以名字