promise bye bye bye(promise结合requestAnimationFrame用法示例)
promise基础用法
js为了解决单线程的异步执行问题 ,引入了事件循环队列体系 ,这个体系里的队列中都是一个个排着队等待执行的宏任务 ,settimeout就是一个宏任务 ,promise是典型的微任务 ,微任务概念是相对宏任务而言的 ,可以把微任务理解为宏任务中的队列 。因为宏任务是按序执行 ,所以如果当前宏任务有微任务 ,只有等当前宏任务的所有微任务执行完毕 ,才会执行下一个宏任务 。所以promise与settimeout不分前后紧挨着出现在代码里,那一定是先执行完promise的回调才会去执行settimeout。这里有一个例子:
输出顺序是c1 、c2 、d ,settimeout后面紧接着一个promise ,那得先执行promise,在promise的then回调中 ,先强行等了一秒钟 ,输出c1后又执行了一个微任务;这一流程走完了,最后才回头执行了settimeout 。这个例子能很好地说明promise(微任务)与settimeout(宏任务)的关系 。
promise结合requestAnimationFrame
promise在项目中会有各种应用场景 ,但是promise结合requestAnimationFrame的用法比较少见 ,我在项目中正好遇到这种需求了 。
先介绍下requestAnimationFrame ,它常常用来写动画 ,相比setInterval 、 settimeout这些更加精确而且性能更好 。前面在介绍promise的时候说到宏任务与微任务的概念 ,requestAnimationFrame也是一种宏任务 。
现在的需求就是要在一个动画结束之后再调用另一个函数 ,这个过程可以简单形象地理解为“图穷匕首见 ” 。
理解requestAnimationFrame
先从mdn 摘个动画的代码 ,理解下requestAnimationFrame的用法:
我在这上面加了点代码 ,可以直接看到效果 。这个官方例子非常值得研究 ,这是我摘抄的原因,有几点要说明下:
step函数的参数timestamp是有值的 ,它是一个double类型的十进制数 ,表示当前回调函数step被调用的时间 两秒后取消动画,动画之所以停止 ,只不过是两秒后 ,没有再触发回调step了 要想取消回调,可以用cancelAnimationFrame ,它的参数是requestAnimationFrame的返回值后面有时间可以研究下requestAnimationFrame的垃圾回收 ,如果在上面的代码中不加条件限制 ,这个持续动画对性能的影响是个值得研究的问题 。
结合promise与requestAnimationFrame
结合上文来看 ,requestAnimationFrame是一个宏任务 ,那在promise中写一个宏任务 ,这事我们经常做 ,就像这样:
那套用到requestAnimationFrame也是一样的 ,结合上面的用法示例 ,我们可以这样写:
需要注意的是,这个promise里面的主体 ,其实是一个requestAnimationFrame函数 ,模型可以简单写成这样:
问题的关键就是回调函数f要写在哪里!?如果写在promise之外,在动画结束 ,需要触发promise的回调时 ,就有问题了,看代码:
据我了解的 ,resolve只能在promise内部调用 ,而Promise.resolve的用法 ,只适合去封装异步函数 ,在这种情况下 ,最好就是像我那样写 ,把requestAnimationFrame和它的回调函数都封装在promiset中 ,等待时机成熟就调用resolve就可以了 。
如果非要写在外面也是有办法的 ,把resolve当作参数传出去,不过要注意的是resolve必须是第二个参数:
这样写的后果就是step的第一个参数失效了 ,不再是一个时间戳了 ,不过你可以自己写一个,动画也可以实现。再强调下resolve要先放在第二个 ,如果你把resolve写在第一个 ,那step得到的resolve就不再是resolve函数,而是一个时间戳 ,这样的话resolve就无法执行了!
参考资料:
developer.mozilla.org/zh-CN/docs/…
stackoverflow.com/questions/6…
以上就是promise结合requestAnimationFrame用法示例的详细内容 ,更多关于promise requestAnimationFrame的资料请关注本站其它相关文章!
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!