setTiemout(fn,0) 用法。

开发过程中,有时发现一个函数debug跟踪一下就执行正常,不跟踪就不执行。然后,加一个setTimeout(fn,0)然后,运行正常了。

今天深入来分析一下这个问题存在的原因。

知识点:

一:js单线程

js执行和主UI线程执行交替进行。 主ui线程又包括paint和redraw(reflow)

二:事件队列(event queue)

dom事件、setTimeout、网络请求事件 都放入事件队列。依次执行。


代码分析:

HTML code:

<table border=1>
    <tr><td><button id='do'>Do long calc - bad status!</button></td>
        <td><div id='status'>Not Calculating yet.</div></td>
    </tr>
    <tr><td><button id='do_ok'>Do long calc - good status!</button></td>
        <td><div id='status_ok'>Not Calculating yet.</div></td>
    </tr>
</table>

JavaScript code: (Executed on onDomReady and may require jQuery 1.9)

function long_running(status_div) {

    var result = 0;
    // Use 1000/700/300 limits in Chrome, 
    //    300/100/100 in IE8, 
    //    1000/500/200 in FireFox
    // I have no idea why identical runtimes fail on diff browsers.
    for (var i = 0; i < 1000; i++) {
        for (var j = 0; j < 700; j++) {
            for (var k = 0; k < 300; k++) {
                result = result + i + j + k;
            }
        }
    }
    $(status_div).text('计算完成');
}

// Assign events to buttons
$('#do').on('click', function () {
    $('#status').text('计算中....');
    long_running('#status');
});

$('#do_ok').on('click', function () {
    $('#status_ok').text('计算中....');
    // This works on IE8. Works in Chrome
    // Does NOT work in FireFox 25 with timeout =0 or =1
    // DOES work in FF if you change timeout from 0 to 500
    window.setTimeout(function (){ long_running('#status_ok') }, 0);
});
一般认为:先显示 status Div,先显示运算中,然后进行运算,并显示运算完成。

运行结果:计算中没有显示,直接运行一会然后显示运算完成。

问题追踪:$('#status').text('计算中....'); dom操作完成后,又产生了一个dom 重绘事件,这个事件放到了js计算后面,结果被计算完成快速覆盖了。




john resig 对timer 的阐述:http://ejohn.org/blog/how-javascript-timers-work/

这个对js的单线程、事件队列讲的很清楚。对js使用timer做重计算的方法也有说明。

stackovflow 对 setTimeout 0 的解释:http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful/23747597#23747597

这里面有个核心。$('#status').text('计算中') 其实也触发了一个事件。是dom重绘的事件。如果,对dom树、dom的paint,redraw了解的不细致。可能就回导致不容易扑捉的问题。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值