JavaScript性能提升之——提升响应速度

首先呢,这里说的响应速度,是指页面UI的响应速度,对一个用户界面来说,评判快的标准是什么?

用户觉得快才是快

优化UI线程

说到底产品最终都是给用户使用的,不论你对自己的产品做了什么优化,在用户手里好用就是好用,快就是快,不是靠你开发者说这说那用了什么技术啊来判定的。那么在网页中,怎么才会显得快呢?

提高用户界面的响应速度一般有两种方式:

  • 提升代码质量来提升响应速度;
  • 让用户觉得你快。

说到提升响应速度,我们得先来说一下浏览器的UI线程。

浏览器UI线程

这个东西呢就是用来执行JavaScript和更新用户界面的进程啦。

UI线程是基于一个简单的队列系统的,所有的任务(UI更新、执行JavaScript)都会被放到任务队列中,任务会被保存到队列中直到进程空闲,一旦空闲,队列中的下一个任务就会被重新提取出来运行。也就是说对浏览器来说,页面上出现的所有事情,执行js、重绘页面这些都要一件件来做。

引用一下 《You Don't Know JavaScript:Types & Grammar,Async &Performance》书中的一段伪代码来解释下这个概念:

//eventLoop是一个用作队列的数组
var eventLoop = [];
var event;

//'永远'执行
while(true){
  if(eventLoop.length>0){
    event = eventLoop.shift();
    try{
      event();
    }
    catch(err){
      reportError(err);
    }
  }
}

结合这段概念代码,实际上我们的页面产生的所有操作,读取、解析资源、渲染页面、重绘,执行js等等这些任务全部都会在队列里排队执行。
当UI线程处于执行任务期间,如果用户在这个时候与之交互,会出现UI没有即时更新,更有可能出现UI的更新任务不会被创建,在我们平时看来就是点击了没反应,连按钮都没一点反馈变化,这种时候就是UI线程处于繁忙状态。

出现这种情况的时候很可能是因为你的js运行时间过长了,现在的浏览器有些会有限制运行时间,超过时间会弹出提示框。这种情况我觉得还是遇到的次数挺多的= =;

相当多的历史研究中有提到过,单个js的操作花费时间不应该超过100ms。

我们自己使用网页的时候也会有感觉,我点了这个按钮过了一会才有反应,完全就给了人一种这网站很慢的感觉。

使用定时器让出UI线程

虽然说单个js任务应该在100毫秒内完成,但是有时候有些任务确实要花费较长时间,这个时候可以使用定时器来让出UI线程使用权,我们在看别人代码的时候应该也有见过设置一个setTimeout任务但是延迟又设置的很低的用法,这就是使用定时器来让出UI线程。

首先要明确的一点是,定时器并不会一执行把你要延迟的任务加入到事件循环队列中,它只是设置定时器到时后,再把你要延迟的这个任务加入到队列中,这也是定时器精度可能不高的原因,因为如果你到时间的时候刚好前面还有很多任务没有被执行完,那你这个只能等啦。

用定时器取代循环

说那么多,什么情况下可以用定时器来做代码块拆分运行优化呢,很常见的js运行时间过长的例子是循环,有些循环处理函数过于复杂或者循环源的大小过大,我们就可以使用,但是这也是有前提的,使用定时器取代循环要满足两个条件:处理过程无需同步,数据无需按顺序处理。
满足这两个条件之后,我们可以写一个简单的函数来处理:

function processArray(items,process,callback){
  var todos = item.concat();
  setTimeout(function(){
    process(tudos.shift());
    if(tudos.length>0){
      setTimeout(arguments.callee,25);
    }else{
      callback(items);
    }
  })
}

只要调用这个函数并传入数组,处理方法与完成的循环完成的回调函数,这样做会使原本的循环时间变成,但是每次循环后都会让出UI线程(上面定时器让出UI线程有说明),不至于说让整个长时间的循环一直占着UI线程而锁定浏览器,虽然实际上的处理时间变长了,但是对用户来说却会觉得更快了。

这种定时器的用法还可以用于分割任务,一个运行时间过长的函数可以试着能不能拆分成多个函数,然后用类似上面的方式来加快UI响应速度。

要注意的是,同时创建多个重复的定时器会产生所有定时器一起抢占UI线程而产生性能问题,最好使用一个定时器每次执行多次操作而不要同时创建多个

使用Web Worker

这个功能属于提供js能以类似多线程的方式来运行的功能,不过实际上并不是。

首先要知道的是,HTML5的Web Worker这个特性属于宿主功能,即浏览器提供的功能,本身和JavaScript语言没关系,JS本身并没有任何支持多线程执行的功能。

浏览器环境可以提供多个JavaScript引擎实例并各自运行独立的线程上。利用web worker,我们就可以将程序划分多块来并发运行。

Web Worker通常被用于以下几个方面:

  • 处理密集型数学计算
  • 大数据集排序
  • 数据处理(压缩、音频分析、图像处理等)
  • 高流量网络通信
    from《You Don't Know JavaScript:Types & Grammar,Async &Performance》

实例化一个Worker很简单: var worker1 = new Worker('http://aa.com/b.js')// 这个url要指向js文件位置;

当这个文件被加载到一个Worker之后,浏览器就会启动一个独立的线程来运行这个Worker。

web worker中使用大多数的标准javascript特性,包括

  • Navigator
  • XMLHttpRequest
  • Array, Date, Math, and String
  • WindowTimers.setTimeout and WindowTimers.setInterval

完整的Web Worker用法可以参考https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers

注意,Worker之间以及他们和主程序之间不会共享任何作用域或者资源,他们之间的联系依靠的是一个基本的事件消息机制来互相联系

Web Worker之间的数据传递

Worker与网页通过事件接口来通信

  • 网页代码使用postMessage()给Worker传递数据
  • Worker可以通过注册 message事件来接收网页传递过来的数据 worker.onmessage = function(event){},传递进来的数据可以通过event.data访问到。
    这是唯一的网页与Worker通信途径

Web Worker的使用场景与浏览器的支持比较有限,就现在来说,常用的场景还是在处理比较大的数据,或者处理与UI无关的长时间运行脚本,比如转换大量的字符串啦,大数据集的搜索排序之类啦。

页面元素的响应处理

这个的话其实主要是从用户体验的角度来“欺骗性的”提高用户对网站速度的印象,怎么说呢

当用户与程序交互的时候,程序要立即给出响应

核心就是上面这句话,立即给出响应不表示你的程序要立即处理完任务,而是要立即做出一个反馈,这个反馈一般会是改变触发交互元素的外观,最常见的就是给可交互按钮添加各种状态,未被触发、触发中、触发后最好都要有个外观变化,这对用户来说是最直观的,无论触发交互的时候任务是否完成,都要立即给予对应的状态来给用户知道我的操作成功了,正在处理,处理好了,不给予反馈的交互过程很容易会让用户认为出了什么问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容