JavaScript笔记整理——驯服线程和定时器

定时器提供了一种让一段代码在一定毫秒之后,再异步执行的能力。由于Js是单线程的(同一时间只能执行一处Js代码)。定时器提供了一种跳出这种限制的方法,以一种不太直观的方式来执行代码。

需要注意的是,定时器并不是Js自身的一个功能。定时器作为对象和方法一部分才能够使用。这也就提醒我们,在非浏览器的环境中使用JS,很可能定时器就不存在了。

1、创建和清除定时器

JavaScript提供了两种方法创建和清除定时器,且这两种方法都是window对象上的方法。如下表:

方 法格 式描 述
setTimeoutid = setTimeout(fn, delay)启动一个定时器,并且在一段时间之后执行传入的callback, 最后返回该定时器的唯一标识
clearTimeoutclearTimeout( id )如果定时器还没触发,出入定时器唯一标识可取消(清除)该定时器
setItervalid = setInterval(fn, delay)启动一个定时器,并且在没个一段时间之后便执行一次传入的callback, 最后返回该定时器的唯一标识
clearIntervalclearInterval( id )传入间隔定时器标识,即可取消(清除)该间隔定时器

2、timeout 和 interval之间的区别

看看下面的代码片段,

// 定义一个timeout定时器,没个10毫秒都重新调度自己
setTimeout(function repeatMe() {

    console.log( ' setTimeout...' );
    setTimeout( repeatMe, 10);

});

// 定义一个interval定时器,每10毫秒都触发一次
setInterval(function() {

    console.log("setInterval...");
});

思考,上面两段代码功能相同吗??

答案是,NO!!

咋一看似乎是相同的,可值得注意的是,setTimeout()代码中,要在前一个callback回调执行结束后并延迟10毫秒以后,才能再次执行setTimeout(); 而setInterval则是每隔10毫秒就尝试执行callback回调,而不用关心上一个回到函数是合适执行的以及是否已经执行结束。


  • Js引擎是单线程执行,异步事件必须要排队等待才能执行。
  • 如果无法立即执行定时器,该定时器贵被推迟到下一个可用的执行时间点上(可能更长,但不会比指定的延迟时间少)。
  • 如果一直被延迟,到最后,Interval间隔定时器可能无延迟执行,并且同一个interval处理程序的多个实例不能同时进行排队。
  • setTimeout() 和 setInterval()在触发周期的定义上是完全不同的。

理解js引擎是如何处理异步代码的,尤其是如何处理通常发生在页面上的大量异步事件,是构成高级应用程序代码的重要基础。

3、定时器延迟时间的可靠性

设想一下,我们设置一个定时器,让它每隔一秒执行一次,执行100次。在这100次中浏览器真的是按照我们所设想的那样每次都是精确的延迟1秒钟执行的吗?? 答案是否定的。

对于不通浏览器来说,它们的定时器延迟时间可靠性差异很大。实际上什么样的延迟值都有。

注意:
IE浏览器有一个缺陷,当我们对interval()设置0毫秒的延迟时,该定时器的callback回调只会执行一次。和使用setTimeout的效果一样。

4、中央定时器控制

几乎所有的动画引擎中都使用一个叫做中央定时器控制(center timer control)的技术。这是因为通常在动画中需要控制和操作很多的属性,这也就需要大量的定时器。但是大量的定时器带来一个严峻的问题:同时创建大量的定时器,无意会在浏览器中增加了垃圾回收的可能性。虽然有些浏览器可以很好的应对这一问题,不过有些浏览器就不那么给力了。这也就是为什么一个动画在一些浏览器中表现的很好 很流畅,但是在另外一些浏览器中却很卡。

在多个定时器中使用中央定时器的好处:

  • 每个页面在同一个时间总需要运行一个定时器;
  • 可以根据需要暂停和回复定时器;
  • 删除回调函数的过程变得很简单;

    下面,让我们看一个使用该技术来管理多个函数的例子:

// 定时器控制对象
var timer = {

    // 记录状态
    timerID: 0,
    timers: [],

    // 添加处理程序
    add: function ( fn ) {
        this.timers.push( fn );
    },

    // 开启定时器
    start: function() {
        if ( this.timerID ) return;
        (function runNext() {
            if ( timers.timers.length > 0 ) {
                for ( var i = 0; i < timers.timers.length; i++ ) {
                    if ( timers.timers[i]() === false ) {
                        timers.timers.splice(i, 1);
                        --i;
                    }
                }

                timers.timerID = setTimeout(runNext, 0);
            }
        })();
    },

    // 停止定时器
    stop: function() {
        clearTimeout( this.timerID );
        this.timerID = 0;
    }

};

5、基于中央定时器控制技术的异步测试

中央定定时器控制带来的另一个便利是在执行异步测试的时候。下面代码,是一个简单的异步测试套件。

(function() {
    // 保存状态表
    var queue = [],
        pause = false;

    // 测试注册函数
    this.test = function( fn ) {
        queue.push( fn );
        runTest();
    };

    // 停止测试
    this.pause = function() {
        pause = true;
    };

    // 回复测试
    this.resume = function () {
        pause  = false;
        setTimeout(runTest, 1);
    };

    // 运行测试
    function runTest() {
        if ( !pause && queue.length ) {
            queue.shift()();
            if ( !pause ) {
                resume();
            }
        }
    }
})();
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 QML 中,可以通过使用 JavaScript 和 Qt QML Timer 组件来实现在新线程中执行定时器。具体步骤如下: 1. 创建一个新的 Worker 对象,并将其绑定到 QML 上下文中。 2. 在 Worker 对象中创建一个新的 Qt QML Timer 对象,并将其设置为自动重复,并设置定时器的时间间隔。 3. 在 Worker 对象中,将定时器的信号与一个 JavaScript 函数连接起来,以便在定时器触发时执行该函数。 4. 在主线程中,通过调用 Worker 对象的 start() 函数来启动新线程。 下面是一个简单的示例代码,演示了如何在 QML 中实现在新线程中执行定时器: ``` import QtQuick 2.0 WorkerScript { id: worker function startTimer() { var timer = Qt.createQmlObject("import QtQuick 2.0; Timer { interval: 1000; running: true; repeat: true }", worker); timer.triggered.connect(handleTimer); } function handleTimer() { console.log("Timer triggered in worker thread"); } } Button { text: "Start Timer" onClicked: { worker.start(); worker.sendMessage({ type: "startTimer" }); } } ``` 在这个示例中,当用户单击按钮时,会启动一个新的 Worker 线程,并在该线程中创建一个新的定时器。当定时器触发时,会执行 handleTimer() 函数。请注意,这个函数是在 Worker 线程中执行的,而不是在主线程中执行的。 如果您需要在定时器中执行更复杂的操作,可能需要使用 Qt 的多线程模块来管理线程和通信。但是,对于简单的定时器任务,使用上述方法可能已经足够了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值