• pace.js 原理(转)


    pace.js监控了什么:

    pace.js对于加载进度监控了什么呢?通过阅读源码,我们看到整体的进度有四个部分组成:document,elements,eventLag和ajax这四种监视器(Monitor)。

    1.

    那接下来就来看看它们分别是什么。

    首先是document。document就是我们所熟悉的HTMLDocument节点。document节点有一个事件,onreadystatechange,当document的readyState状态变化时会触发。因为无法准确的知道document到底加载了多少百分比,所以就用这个状态来做一个估算。在pace.js中将document的readyState的三个状态loadong,interactive和complete分别定义为0%,50%和100%。通过监听document节点的readyState状态变更,形成了pace.js的DocumentMonitor。

    2.

    接下来是elements。我们可以通过配置传入一个css选择器列表,默认的选择器列表仅包含“body”。pace.js会按照设置的时间间隔搜索所有的选择器,如果能获得则认为这一项满足,所以elements这一项的加载进度就是 满足的选择器/全部的选择器。通过查询页面中制定的元素,就是pace.js的ElementMonitor。

    3.

    然后是eventLag。EventLagMonitor其实只是一个“假的”监视器。它就在那里安静匀速的更新进度,这一小小的措施却带来了不错的用户体验,让用户不会因为加载“卡住了”而慌张。

    pace.js是如何监控ajax的:

    最后是用来监控ajax进度的AjaxMonitor。这是最有趣的一部分。如何才能监控所有ajax请求,并且不需要开发者修改自己或第三方的业务逻辑呢?

    如果了解原生js的话,应该了解这几个类:XMLHttpRequest,XDomainRequest,WebSocket。这三个类分别用来发送ajax请求,跨域的ajax请求,以及websocket。如果能监控所有这些请求的时间,包括progress,load,error等等,我们就可以更新我们的加载进度了。

    既然我们知道了要监控的对象,那我们便可以“请君入瓮”了,而这个瓮,就是代理模式:我们可以把原生的类保存起来,再用我们自己写的埋藏了“间谍”的类覆盖原生的类,这样当其他代码建立这些类的实例的时候,我们的“间谍”便悄悄开始监听加载进度了。

    让我们来看一下代码:

    // 保存原生的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,可以监控制定函数被调用了几次,被什么参数调用了等等。灵活应用这种代理模式,可以方便我们扩展功能、进行调试等等。

  • 相关阅读:
    Go语言 插入排序并返回排序前的索引
    使用patch-package定制node_modules 中的依赖包
    移动端 rem自适应布局 (750的设计稿)
    通过原型截获input.value的方法
    ts 使用 keyof typeof
    logrotate日志管理工具
    【LeetCode刷题】239.滑动窗口最大值
    【LeetCode刷题】剑指Offer 48.最长不含重复字符的子字符串
    【LeetCode刷题】912. 排序数组
    【LeetCode刷题】744. 寻找比目标字母大的最小字母
  • 原文地址:https://www.cnblogs.com/eret9616/p/9783407.html
Copyright © 2020-2023  润新知