setTimeout的骚操作

先回顾一下定时器的一些重要知识:

1、Javascript引擎是单线程执行,异步事件必须要排队等待才能执行。

2、如果无法立即执行定时器,该定时器会被推迟到下一个可用的执行时间点上(可能更长,但不会比指定的延迟时间更少)。

3、如果一直被延迟,到最后,Interval间隔定时器可能会无延迟执行,并且同一个interval处理程序的多个实例不能同时进行排队。

4、setTimeout()和setInterval()在触发周期的定义上是完全不同的。

下面是今天的例子。

通常在我们计算大量数据的时候,比如在操纵成千上万个dom元素的时候,可能会出现一种情况---不响应的用户界面,如下面这段代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <table><tbody></tbody></table>
</body>
</html>
<script type="text/javascript">
    var tbody = document.getElementsByTagName('tbody')[0];
    for(var i = 0; i < 20000; i++) {
        var tr = document.createElement("tr");
        for(var t = 0; t < 6; t++) {
            var td = document.createElement("td");
            td.appendChild(document.createTextNode(i + "," + t));
            tr.appendChild(td);
        }
        tbody.appendChild(tr);
    }
</script>

在本例中,我们创建了240000个dom节点,并使用大量的单元格来填充一个表格。这是非常昂贵的操作,明显会增加浏览器的执行时间,从而阻止正常的用户交互操作。

在浏览器中执行该代码段,会发现浏览器的刷新按钮有较长一段时间都是正在加载的状态。

接下来我们引入定时器来改善这段代码----即在代码执行的时候定期暂时休息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <table><tbody></tbody></table>
</body>
</html>
<script type="text/javascript">
    //建立初始数据
    var rowCount = 20000;
    var divideInto = 4;
    var chunkSize = rowCount/divideInto;
    var iteration = 0;

    var table = document.getElementsByTagName("tbody")[0];

    setTimeout(function generateRows() {
        //计算上次中断的地方
        var base = (chunkSize) * iteration;
        for(var i = 0; i < chunkSize; i++) {
            var tr = document.createElement("tr");
            for(var t = 0; t < 6; t++) {
                var td = document.createElement("td");
                td.appendChild(document.createTextNode((i + base) + "," + t + "," + iteration));
                tr.appendChild(td);
            }
            table.appendChild(tr);
        }
        iteration++;
        //调度下一个阶段
        if(iteration < divideInto) {
            setTimeout(generateRows, 0)
        }
    }, 0)
</script>

在该修改版本的事例中,我们将冗长的操作拆分成四步小操作,每个操作创建自己的dom节点、这些较小的操作,则不太可能让浏览器挂掉。

注意:我们是如何进行设置的,以便让数据值得控制操作可以根据变量很容易地调整,比方说,我们应该发现,我们需要将操作拆分成10个部分,而不是4个部分。

还有一个与数学有点关系的重要内容需要注意,我们需要跟踪上一次迭代中断的地方,以及如何自动安排下一个迭代,一直到全部结束。

再次在浏览器中运行该段代码,会发现页面几乎在不感知的情况下加载完这么多dom节点了~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值