从SetTimeout例子理解JS异步和同步执行

看到两篇关于JS 同步任务和异步任务的文章,进行一下整理。

当即有宏任务,微任务时,执行过程是
宏任务 -> 微任务 -> GUI渲染 -> 宏任务

文章中例子也比较有说明意义。

document.body.style = 'background:black';
document.body.style = 'background:red';
document.body.style = 'background:blue';
document.body.style = 'background:grey';

虽然前后设置了4次背景色,却都是一个任务中按顺执行,因此只会在代码执行完后,以最后的背景色为最终值进行渲染,且没有多余宏wtt,渲染仅执行一次。

document.body.style = 'background:blue';
setTimeout(function(){
    document.body.style = 'background:black'
},0)

上面这个示例中setTimeout是额外的宏任务,合计有两个宏任务(主程序也是宏任务),则执行顺序为

主任务 -> GUI渲染 -> setTimeout宏任务 -> GUI渲染
因此,页面会渲染两次,有明显的变化。

document.body.style = 'background:blue'
Promise.resolve().then(()=>{
    document.body.style = 'background:black'
});

再看另一个示例,如上,此时利用promise增加回调,其中promise是一个微任务,执行顺序为

主任务 -> 微任务 -> GUI渲染
因此,页面只渲染一次

从上可以看到,setTimeout 和Promise的处理相关比较大。

思考

SetTimeInterver重复触发补充
结论:经过验证,并没有多个timeinter存在时,会忽略中间的回调,实际上是每次interver都会按序触发。

console.log('start')
var count = 0;
var startTime = new Date().getTime();
var iid = setInterval(test, 1000);
function test() {
    count++;
    sleep(2000);
    if(count >= 4){
        clearInterval(iid)
    }
    console.log(new Date().getTime() - startTime, 'count', count);
}
function sleep(sleepTime){
    var start = new Date().getTime();
    while(true){
        if(new Date().getTime()-start>sleepTime){
            break;
        }
    }
}

参考

  • 页面背景渲染
  • 买奶茶

你可能感兴趣的:(javascript)