OurJS


OurJS-我们的JS, 我们的技术-IT文摘; 专注JS相关领域;
我们热爱编程, 我们热爱技术;我们是高大上, 有品味的码农;

欢迎您订阅我们的技术周刊


我们会向您分享我们精心收集整理的,最新的行业资讯,技术动态,外文翻译,热点文章;
我们使用第三方邮件列表向您推送,我们不保存您的任何个人资料,注重您的隐私,您可以随时退订,

欢迎分享您的观点,经验,技巧,心得

让我们一起找寻程序员的快乐,探索技术, 发现IT人生的乐趣;


本网站使用缓存技术每次加载仅需很小流量, 可在手机中流畅浏览;
如果您发现任何BUG,请即时告知我们: ourjs(at)ourjs.com

JavaScript中该如何安排后台任务


分享到
分类 心得体会   关键字 JavaScript   发布 ourjs  1466039014699
注意 转载须保留原文链接,译文链接,作者译者等信息。  

译者: cncuckoo  

关于JavaScript,大家要牢记一点:它阻塞

想象一下,浏览器里有一个进程小精灵,负责处理一切。渲染HTML、响应菜单命令、绘制屏幕、处理鼠标点击、运行JavaScript函数……。跟我们人一样,这个小精灵每次只能做一件事。如果一次交给它很多任务,那么就会有一个待办事项列表,小精灵按顺序一项一项去处理。

小精灵在碰到script标签或者要运行JavaScript函数时,会停下其他任务。下载代码(必要时)然后立即运行,之后才会触发其他事件 ,以及渲染页面。这是必要的,因为脚本几乎什么都可能做:加载更多代码、删除DOM元素、重定向URL,等等。就算有两个甚至更多小精灵,那其他小精灵也需要在首次处理代码时停下来。这就是阻塞。这也是为什么运行时间过长的脚本会导致浏览器无响应的原因。

我们通常想让JavaScript尽快运行,因为代码要初始化部件和事件处理程序。可是,有些没那么重要的后台任务并不会直接影响用户体验,比如:

  • 记录分析数据
  • 向社交网络改送数据(或发送57个“分享”按钮)
  • 预先取得内容
  • 预先处理或预先渲染HTML

这些任务并不要求立即完成,而为了保证页面持续响应,不应该在用户滚动页面或浏览内容期间执行这些任务。

为此可以使用Web Workers,在另一个线程里并发地运行代码。这个技术非常适合预先取得和处理数据,但无权直接访问或修改DOM。你可保证自己的脚本不那么干,但却无法保证Google Analytics等第三方脚本不那么干。

还有一个选择是setTimeout,比如setTimeout(doSomething, 1);。浏览器会在立即执行的任务完成后紧接着执行doSomething()函数。实际上是把它放在了待办事项的最后一项。问题在于无论有没有处理需求,这个函数都会被调用。

requestIdleCallback

requestIdleCallback是新API,用于在浏览器空闲的时候安排一些没那么重要的后台任务。这个API会让人联想到requestAnimationFrame,后者会在下一次绘制前调用函数更新动画。具体内容可以参考这篇文章:Simple Animations Using requestAnimationFrame

可以这样检测浏览器是否支持requestIdleCallback

if ('requestIdleCallback' in window) {
  // 支持requestIdleCallback
  requestIdleCallback(backgroundTask);
}
else {
  // 不支持,换一种方式
  setTimeout(backgroundTask1, 1);
  setTimeout(backgroundTask2, 1);
  setTimeout(backgroundTask3, 1);
}

还可以通过一个选项对象参数,指定暂停时间(以毫秒计),比如:

requestIdleCallback(backgroundTask, { timeout: 3000; });

这样可以保证你的函数在三秒钟内执行,无论浏览器是否空闲。

requestIdleCallback只会调用一次你的函数,并传入一个包含以下属性的期限(deadline)对象:

  • didTimeout — 如果可选的暂停时间已到则为true
  • timeRemaining() — 函数,返回留给任务执行的毫秒数

timeRemaining()会给你的任务分配不超过50ms的执行时间。它不会让任务停止超过这个时间限制,不过你可以再次调用requestIdleCallback以安排进一步的处理。

下面看一个例子,按顺序执行几个任务。任务以函数引用形式保存在一个数组中:

// 要运行的函数数组
var task = [
  background1,
  background2,
  background3
];

if ('requestIdleCallback' in window) {
  // 支持requestIdleCallback
  requestIdleCallback(backgroundTask);
}
else {
  // 不支持,待会一次性运行所有任务
  while (task.length) {
    setTimeout(task.shift(), 1);
  }
}

// requestIdleCallback回调函数
function backgroundTask(deadline) {

  // 有可能的话运行下一个任务
  while (deadline.timeRemaining() > 0 && task.length > 0) {
    task.shift()();
  }

  // 还有未执行的任务,再次申请处理
  if (task.length > 0) {
    requestIdleCallback(backgroundTask);
  }
}

有没有什么不应该通过requestIdleCallback做的

正如Paul Lewis在他关于这个主题的博客文章所说的,requestIdleCallback应该执行小任务,不适合执行时间不确定的任务(像操作DOM,最好还是用requestAnimationFrame回调来做)。在resolve(或reject)Promise的时候也要注意,因为空闲回调完成后会立即调用Promise的回调,而不管剩下的时间还够不够执行该回调。

requestIdleCallback的浏览器支持情况

requestIdleCallback是一个实验性的API,规范仍在制定中,今后很可能有改动。Chrome 47支持它,Opera应该也会跟进。Microsoft和Mozilla都在关注它,前景不错。Apple照例没有表态。如果你现在就想试一试,最好用Chrome Canary

Paul Lewis写了一个简单的requestIdleCallback“垫片脚本”,实现了上述API的行为,但它不是一个可以模拟浏览器空闲检测行为的“腻子脚本”。他使用的是类似前面例子中的setTimeout。不过,如果你不想依赖对象检测也不想写分支代码,用这个脚本还是不错的。

虽然今天的浏览器对requestIdleCallback的支持有限,但这个API的确非常有助于提升网页性能。你对此有什么想法吗?欢迎留言。

原文地址: 点此
社区评论 ( Beta版 )
OnceDoc 您自己的企业内容管理系统——文档、流程、知识库、报表、网盘All In One

访问404页面,寻找丢失儿童
 热门文章 - 分享最多
  1. Web前端面试题集锦
  2. 基础 JavaScript 装X指南
  3. Node.js单元测试、集成测试、基准测试以及代码覆盖率测试方面总结
  4. You Don't Need jQuery
  5. 如日中天的Uber究竟使用什么开发语言?
  6. 10个常见的Node.js面试题
  7. 高危漏洞-ImageMagick图象处理软件存在远程代码执行漏洞
  8. Node.js面试题:侧重后端应用与对Node核心的理解
  9. NodeJS中用child_process的exec执行cd指令为什么不工作?
  10. 前端开发前景怎么样 ?大神为您全面解析!
  11. AirJD-简单好用的免费建站工具

 相关阅读 - 心得体会
  1. Markdown 语法简介和使用说明-详细版
  2. JavaScript正在变成Web界的C++
  3. 请停止将JavaScript类型化(建议不要使用class实现类继承)
  4. 几款开源的图形化Redis客户端管理软件
  5. 我为什么不再用Compass写CSS(缺点分析)
  6. CSS Sprite小图片自动合并工具(NodeJS,Python,Java,Ruby)
  7. 即将推出的CSS4 Level 4 Selectors(第4级选择器)
  8. 主流JavaScript MVC框架性能比较测试:Angular vs Backbone vs Ember
  9. [译]Node.js 框架比较: Express vs. Koa vs. Hapi
  10. 从PhantomJS迁移到node-webkit:自动化测试框架简单比较

 关键字 - JavaScript
  1. 如何用CSS将select/option文本居中或居右对齐
  2. 你用什么代码编辑工具开发JavaScript?
  3. JavaScript条形码生成和扫码识别(Barcode scan)开源库
  4. 40行JavaScript代码实现的3D旋转魔方动画效果
  5. 使用Javascript将相对路径地址转换为绝对路径
  6. 给checkbox选择框设置不选中时的值
  7. 用原生HTML5控件实现输入框自动提示(下拉列表补全)功能
  8. JavaScript中怪异的地方
  9. 在JavaScript中创建命名空间的几种写法
  10. JavaScript中的继承,构造函数以及new关键字的作用

 欢迎订阅 - 技术周刊

我们热爱编程, 我们热爱技术; 我们是高端, 大气, 上档次, 有品味, 时刻需要和国际接轨的码农; 欢迎您订阅我们的技术周刊; 您只需要在右上角输入您的邮箱即可; 我们注重您的隐私,您可以随时退订.
加入我们吧! 让我们一起找寻码农的快乐,探索技术, 发现IT人生的乐趣;


 关注我们

我们的微信公众号: ourjs-com
打开微信扫一扫即可关注我们:
IT文摘-程序员(码农)技术周刊

ourjs官方微信号