Pace.js的原理是怎么样的

如题所述

只要在页面上引入pace.js和相关的css,并不需要对业务逻辑做什么修改,就能拥有网页加载进度条,只要大家发挥想象力,那除了默认的进度条之外还能开发各种加载进度效果,使用起来非常方便。
那问题来了:pace.js是如何做到“自动”监控加载进度的呢?
pace.js监控了什么:
pace.js对于加载进度监控了什么呢?通过阅读源码,我们看到整体的进度有四个部分组成:document,elements,eventLag和ajax这四种监视器(Monitor)。
那接下来就来看看它们分别是什么。
首先是document。document就是我们所熟悉的HTMLDocument节点。document节点有一个事件,onreadystatechange,当document的readyState状态变化时会触发。因为无法准确的知道document到底加载了多少百分比,所以就用这个状态来做一个估算。在pace.js中将document的readyState的三个状态loadong,interactive和complete分别定义为0%,50%和100%。通过监听document节点的readyState状态变更,形成了pace.js的DocumentMonitor。
接下来是elements。我们可以通过配置传入一个css选择器列表,默认的选择器列表仅包含“body”。pace.js会按照设置的时间间隔搜索所有的选择器,如果能获得则认为这一项满足,所以elements这一项的加载进度就是 满足的选择器/全部的选择器。通过查询页面中制定的元素,就是pace.js的ElementMonitor。
然后是eventLag。EventLagMonitor其实只是一个“假的”监视器。它就在那里安静匀速的更新进度,这一小小的措施却带来了不错的用户体验,让用户不会因为加载“卡住了”而慌张。
pace.js是如何监控ajax的:
最后是用来监控ajax进度的AjaxMonitor。这是最有趣的一部分。如何才能监控所有ajax请求,并且不需要开发者修改自己或第三方的业务逻辑呢?
如果了解原生js的话,应该了解这几个类:XMLHttpRequest,XDomainRequest,WebSocket。这三个类分别用来发送ajax请求,跨域的ajax请求,以及websocket。如果能监控所有这些请求的时间,包括progress,load,error等等,我们就可以更新我们的加载进度了。
既然我们知道了要监控的对象,那我们便可以“请君入瓮”了,而这个瓮,就是代理模式:我们可以把原生的类保存起来,再用我们自己写的埋藏了“间谍”的类覆盖原生的类,这样当其他代码建立这些类的实例的时候,我们的“间谍”便悄悄开始监听加载进度了。
让我们来看一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

// 保存原生的XMLHttpRequest
_XMLHttpRequest = window.XMLHttpRequest;

// 覆盖XMLHttpRequest
window.XMLHttpRequest = function(flags) {
var req;
// 调用原生的XMLHttpRequest
req = new _XMLHttpRequest(flags);
// 埋入我们的“间谍”
monitorXHR(req);
return req;
};

monitorXHR = function(req) {
var _open;
// “间谍”又对open方法埋入了间谍
_open = req.open;
return req.open = function(type, url, async) {
if (shouldTrack(type)) {
_this.trigger('request', {
type: type,
url: url,
request: req
});
}
return _open.apply(req, arguments);
};
};

通过代理模式埋了这些“间谍”后,我们就能对发起的ajax请求等做到监控,以更新加载进度。
当然pace.js也不是什么都监听了
除了以上这些,当然也有pace.js并没有监听的加载事件,比如script标签的加载。如果我们使用了sea.js或者require.js等,当js代码动态加载时并不会影响进度条,因为这里我们用动态建立script标签的方式加载js代码,而pace.js并没有对这方面进行监听。我们可以同样的代理appendChild方法,如果发现script标签被加到页面上,那么就监听它的加载进度。不过实际情况当然复杂的多,还有insertBefore,甚至innerHTML等方法都可以创建script标签加入文档并开始js的加载(当然一般就是appendChild和insertBefore啦)。
相似的还有css的加载,还要注意处理css的加载事件,在一些老的浏览器上,css并没有加载事件,还有加个定时不断检查css节点的cssRules和name来确定加载状况。
小结:
通过阅读pace.js的源码我们了解了pace.js的原理,同时学习了鸡贼的代理模式。比如在jasmine.js中也有个spy,可以监控制定函数被调用了几次,被什么参数调用了等等。灵活应用这种代理模式,可以方便我们扩展功能、进行调试等等。
温馨提示:内容为网友见解,仅供参考
无其他回答

Pace.js的原理是怎么样的
通过监听document节点的readyState状态变更,形成了pace.js的DocumentMonitor。接下来是elements。我们可以通过配置传入一个css选择器列表,默认的选择器列表仅包含“body”。pace.js会按照设置的时间间隔搜索所有的选择器,如果能获得则认为这一项满足,所以elements这一项的加载进度就是 满足的选择器\/全部的选择...

Pace.js的原理是怎么样的
基本上是几种中方案的混合 1、document.onreadystatechange 该事件读 document.readyState 字符串 { loading: 0, interactive: 50, complete: 100 } 分别给出写死的进度值 2、如果支持 ProgressEvent 事件 监听 progress 事件 evt.loaded \/ evt.total 得出进度 3、onreadystatechange 事件 ...

sonija,evonne,charlie ,pace分别是谁的英文名
Evonne是许慧欣 Pace是吴佩慈 那两个我不知道

js body class pace-running 怎么忽略
int inthestr(char *s,char ch){ while(*s!='\\0'){ if(*s==ch)return 1;s++;} return 0;}

口袋怪兽中的便利键是键盘上的那个键?
如果你没有重设按键那么就应该是退格键(回车上面那个)按开始键,然后打开背包,选择要登陆的装备,例如选择钓鱼竿,在钓鱼竿处按下A键,然后选择登陆就可以了。关掉背包,在正常状态下按选择键就可以不通过背包使用钓鱼竿了(在河边!)便利键的确很好用 ...

2500元组装台式电脑,主要家用看电影听歌打小游戏,显示器要好点的...
硬盘:ST500G ¥270 光驱:先锋刻录 ¥165 机箱:普通 ¥80 电源:长城额定300W ¥145 显示器:AOCE936VW ¥750 ¥2490 注:显示器为LED屏。如去装机,商家可能会在此基础上加一百多块,光驱不知你是否必须配置,如不配,将光驱去掉,2500一定能拿下此配置。

为什么我的这段js不兼容火狐...急!在线等...
首先确定下载正常IE下能否运行。如果真的是在IE下正常,而在FF下不对,那么可能是你调用时的问题了 注意非IE浏览器 只可能通过 document.getElementById来获取对像。看看你在调这个函数时是否是用expandIt(对像ID名),这个就不对了,正确标准的写法是 expandIt(document.getElementById('对像ID名'))...

日文输入法下,\\\\\\是哪个键输入的?
backspace和enter中间那个键,就是汉语输入顿号(、)那个键。在日文输入的状态下按一次显示¥,再按一次就变成\\\\了。剩下的需要几个按几次就可以了。

节奏感够强 而且好听的歌 谁能告诉我一些
起点是... 终点是...js这张专辑的最后一支曲,象征着旅行的开始和结束的概括,曲头是很抒情的小调,忽然又节奏话了,让人一下振奋起来,钢琴的间断性穿插和大提琴的贯穿后音,让人感觉很轻松。 其他的是两首环境音,分别是飞机场的起飞和返程时的声音,也分别穿插在专辑的第一首和最后一首 整张专辑贯穿起来听 ...

keep的过去式和过去分词是什么_keep的英语知识
9. With four laps to go, he kept pace with the leaders.还剩4圈的时候,他紧紧咬住领先者。10. The prison's inmates are being kept in their cells.这个监狱的犯人被关在他们的囚室里。<<< keep的例句 v. 保持;保留;继续;贮藏;经营;遵守;供给;照管; 饲养 ;耽搁;保持食物不变质;...

相似回答