最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • setInterval和requestAnimationFrame的区别,以及引发的思考

    正文概述 掘金(guoss)   2021-02-07   741

    在canvas动画的文章中用到了requestAnimationFrame,丢弃了传统中使用的setInterval

    setInterval

    以固定的时间间隔,重复运行一段代码.

    requestAnimationFrame

    setInterval()的现代版本;在浏览器下一次重新绘制显示之前执行指定的代码块,从而允许动画在适当的帧率下运行,而不管它在什么环境中运行. 那么两者的相同之处呢?都是作为Javascript单线程中异步而存在的。

    Javascript单线程

    进程和线程

    进程就好比工厂(GPU)的车间,而车间的工人就是线程。每个车间独立运作,工人协同合作完成工作。
    1.一个进程包含多个线程,进程的内存空间是线程共享的
    2.进程是相互独立的
    3.进程是操作系统分配的最小单位,线程是程序运行最小单位

    浏览器中线程

    定时器线程

    浏览器定时计数器是一个单独的线程,触发定期行为后进入事件触发线程。
    假设是在javascript线程,会因为阻塞导致计数不准确。

    事件触发线程

    当一个事件(鼠标点击、ajax请求、定时器等)触发后,会添加到队列中,等待计js线程处理。

    异步http请求线程

    浏览器有一个单独的线程用于处理ajax请求,当有回调时,进入事件触发线程

    javascript线程

    负责处理解析和执行javascript脚本程序

    GUI 渲染线程

    选择浏览器中html,以及对应的重绘。在javascript线程运行脚本期间,GUI是被暂时挂起的

    Event Loop事件循环机制

    我最初的理解是:
    同步的任务在js线程上执行,形成一个执行栈;setTimeout、setInterval和requestAnimationFrame中的回调作为js中的异步任务,通过触发对应的线程,将回调放入事件队列中;执行栈中的内容执行完成后,GPU会进行重绘,然后js引擎会通过系统去读取事件队列中的内容,将内容放在执行栈中执行。
    在实际的过程中呢?
    在事件循环的过程中,异步事件返回的结果会被放在事件队列中。根据异步事件的类型,异步事件会被分为宏任务和微任务队列中。执行栈先去执行宏任务,当宏任务中内容为空,主线程会查看当前的微任务是否有事件存在,如果不存在会去执行下一次宏任务,如果存在,先执行当前的微任务。
    setInterval和requestAnimationFrame的区别,以及引发的思考
    异步任务解释, event-loop。 浏览器中的宏任务主要包含定时器、io操作,微任务主要是promise、async,requestAnimationFrame姑且作为一种特殊的任务,在执行完微任务后触发。MDN中讲到:告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
    首先一个简单的例子:

    document.body.style = 'background:blue'
    console.log(1)
    new Promise(res=>{
      document.body.style = 'background:gray'
      console.log(2)
      res(2)
    }).then((r)=>{
      console.log(r)
      document.body.style = 'background:black'
    })
    console.log(3)
    setTimeout(() => {
      console.log(4)
      document.body.style = 'background:pink'
    }, 10)
    

    控制台最终效果1、2、3、2、4。
    1.执行宏任务中的内容颜色变蓝
    2.打印1
    3.颜色变灰
    4.打印2
    5.打印3
    6.执行微任务中的打印promise返回结果2
    7.颜色变黑
    8.GPU渲染
    9.执行新的宏任务
    10.打印4
    11.颜色变粉
    浏览器的样式为先黑色在变成粉色,会忽略掉第三个步骤,因为这个时候微任务还没有执行完,所以重绘的时候颜色会直接变成黑色 接下来看一个相对复杂的例子

    console.log(1)
    setTimeout(() => {
      console.log('setTimeout')
    }, 10);
    new Promise((res,rej)=>{
      res(11)
      console.log("Promise")
    }).then(res=>{
      console.log(res+"PromiseThen")
    }).catch(rej=>{
    
    })
    window.requestAnimationFrame(()=>{
      console.log('requestAnimationFrame')
    })
    console.log("hah")
    let aa = new Promise((res,rej)=>{
      res(2)
    })
    
    async function bb() {
      let a = await aa;
      try {
        console.log(a+"try")
      } catch (error) {
        console.log(a+"catch")
      }
    }
    bb()
    console.log("end")
    

    所以打印结果如下:
    1----Promise----hah----end----11PromiseThen----2try----requestAnimationFrame----setTimeout
    这里的执行顺序:
    1.宏任务开始 打印1 2.触发定时器线程、将回调放入事件队列中
    3.promise打印promise,将promise的回调放入当前的微任务中
    4.打印hah
    5.继续执行promise,将回调放入微任务中
    6.打印end
    7.执行当前的微任务,打印console.log(res+"PromiseThen")打印11PromiseThen
    8.执行当前的微任务,打印console.log(a+"try")打印果2try
    9.执行requestAnimationFrameconsole.log('requestAnimationFrame')打印requestAnimationFrame
    10.GUP渲染
    11.执行下次宏任务定时器中的console.log('setTimeout')打印setTimeout


    下载网 » setInterval和requestAnimationFrame的区别,以及引发的思考

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元