zoukankan      html  css  js  c++  java
  • 昼猫笔记 JavaScript -- 异步执行 | 定时器真的定时执行?

     

    本篇主要内容:异步、定时器引发的思考

    预计阅读时间:8分钟


    了解

    我们都知道在js中定时器有两种  setInterval()  、 setTimeout()  
    setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到  clearInterval()  被调用或窗口被关闭。 
    setTimeout() :在指定的毫秒数后调用函数或计算表达式。 
    那么问题来了,定时器真的是定时执行的吗? 刚开始我认为定时器肯定是定时执行的啊,要不然怎么会叫做定时器呢,后来我感觉我好像错了,所以今天就来说说这个问题 定时器真的是定时执行的吗


    测试

    1 var start = Date.now()
    2 console.log('启动定时器前...')
    3 setTimeout(function () {
    4    console.log('定时器执行了: ', Date.now()-start)
    5 }, 100)
    6 console.log('启动定时器后...');

    我们会发现定时器执行了101ms, 一般会延迟一丁点(可以接受),说白了就是准确的,如果说300ms之后执行呢?

    var start = Date.now()
    console.log('启动定时器前...')
    setTimeout(function () {
       console.log('定时器执行了: ', Date.now()-start)
    }, 100)
    console.log('启动定时器后...');
    for (var i = 0; i < 1000000000; i++) {
    
    }


    如果像上边这种情况,本来是200ms,但是现在变成了1941ms,那还合适吗? 
    也就是说我们的定时器真的能保证定时吗? 
    答案是不能,也可能延迟执行,是在原有设定的时间上又有延迟,加入本来是200ms, 那么现在是1941ms,所以说定时器并不能真正保证定时执行

    注意:定时器的回调函数是在主线程执行,无论是非回调函数还是回调函数都是在主线程执行


    JS执行方式

    这时候就说到了一个概念 --- js是单线程执行的 
    那如何证明js执行是单线程的呢?尤其是一些回调函数中,我们把握不住是主线程执行还是分线程执行的,所以我们现在就验证下js是单线程执行的

    setTimeout(function () {
       console.log('timeout 2')
    }, 2000)
    
    setTimeout(function () {
       console.log('timeout 1')
    }, 1000)
    function fn () {
       console.log('fn()');
    }
    fn()
    console.log('alert之前')
    alert('提示...')
    console.log('alert之后')


    执行流程:fn() alert之前 弹窗 


    当我点击确认后,  timeout 2  和  timeout 1  是立即执行还是过一会执行 


    alert之后 timeout 1 timeout 2 


    我们发现是过一会执行,所以说 
    alert() 的作用是暂停当前主线程,同时暂停计时。 点击确认后,回复程序执行和计时

    小结 
    如何证明js执行是单线程的? 
    setTimeout()  的回调函数是在主线程执行的 
    定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行

     

    setTimeout(function () {
       alert('2222222')
       console.log('timeout 2')
    }, 2000)
    
    setTimeout(function () {
       alert('1111111')
       console.log('timeout 1')
    }, 1000)
    function fn () {
    
       console.log('fn()');
    }
    fn()
    console.log('alert之前')
    alert('提示...')
    console.log('alert之后')

    其实呢到现在咱们也不能清楚地看到JS是如何执行的,要说到这个,我们就得说下代码分类,之前也写过代码分类,全局代码和函数局部代码。 


    代码分类

    这一次呢我们分为初始化代码和回调代码 
    回调代码就是回调函数中的代码 

    setTimeout  是本文的初始代码 


    接下来就是比较重要的一段函数了 

    setTimeout(function () {
       console.log('timeout 0')
    }, 0)
    console.log('昼猫')

     

    这一段代码中是谁先执行? 


    总结 

    JS引擎执行代码的基本流程: 
    先执行初始化代码:包含一些特别的代码,例如:设置定时器、绑定事件监听、发送ajax请求 
    在后面在某个时刻才会执行回调代码 
    回调函数我们平常时候会说是异步执行 
    也就是说某些代码(某些东西)必须在所有的初始化代码执行后才有可能得到被执行,这样的代码我们成为异步代码

     

     孔子东游记               公众号:昼猫笔记


    文章转载公众号昼猫笔记


  • 相关阅读:
    jsp 生成验证码代码
    成为Java顶尖程序员 ,看这11本书就够了
    自动清除浏览器缓存-Cache Killer
    移动端-ios-上拉加载卡顿
    移动端-ios-点击阴影去除
    转--Android开发实践:使用Service还是Thread
    Android入门:Handler简介与实例
    Spring事务的隔离级别
    ThreadLocal的内存泄漏问题
    Spring 使用注解方式进行事务
  • 原文地址:https://www.cnblogs.com/zhoumao/p/10098780.html
Copyright © 2011-2022 走看看