针对页面的全部静态图片加载情况上报服务器的思考🤔

最近遇到一上神,称他为上神,是基于他的识人能力、对行业痛点的思考以及解决问题的能力,这些都足以让他成为我的师傅,其实我跟他也就简单的聊十几分钟,他就可以找到我的问题所在,帮我认识自己,这是自我认知的有效途径之一。

我的问题一:不爱思考

其实在两年前,我就知道我有这个毛病,没想到我认为的小毛病,现在却成为限制我发展的瓶颈。当上神指出我的问题的时候,我还“狡辩”说,太过于专注业务的开发,而没去做这些思路。上神指责我,我思维就有问题,在做的时候就应该思考,而不是只做不思考。

培养思维

想想也是只有不断的思考,抛出问题,虽然当时没有搞懂,没有满意的答案,但是脑海里有这个问题库。在后面的读书、查资料、做业务、沟通交流的时候,就能碰上每个问题,就消灭掉一个问题。与此同时,随着问题的抛出,问题的延伸,自然而然对这个领域有了一定的思想沉淀,不管是深度和广度上都有了一定的扩展。

修炼内功

我也不应该去逃避现实,面对自身的短板,去调整自己才是上上策,才能迎接更好的自己。只有达到一定的层次,夯实基础才有资格成为上神的徒弟。毕竟我算不上天赋异禀,没有深厚的内功。上神又有什么理由要收我为徒。

如何监听当前页面上的所有img图片的加载情况

言归正传,回到今天的主题:如何监听当前页面上的所有img图片的加载情况,每张图片什么时候开始加载,什么时候加载成功,或者加载失败。将图片的加载情况汇总,然后上报到服务器。

最初思考

最近在做vue项目,找了一个正在开发业务练手,我选择在mounted生命周期里去处理。

最初的思路是:先获取到当前页面所有的img图片,遍历所有图片,遍历到每张图片开始记录加载开始时间,同时监听图片的加载成功、失败、缓存的时间以及状态。计数统计处理的图片,当统计完成,向服务上报。

imgLoadCtrl();

function imgLoadCtrl() {
  let imgs = document.querySelectorAll('img');
  let arr = [] // 图片的加载情况
  let count = 0 // 图片加载完成张数(包含加载失败图片 和缓存图片)
  let progress = 0 // 图片加载进度

  // console.time()
  Array.from(imgs).forEach((item, index) => {
    arr[index] = {
      startTime: +new Date()
    };

    // 获取新加载的图片
    item.onload = (e) => {
      addLoadMessage(arr, item, index, 'loadFinished')
    }

    // 获取加载失败的图片
    item.onerror = (e) => {
      addLoadMessage(arr, item, index, 'loadError')
    }

    // 获取缓存的图片
    item.oncomplete = (e) => {
      addLoadMessage(arr, item, index, 'loadCache')
    }
  })

  // 图片加载情况数据整理
  function addLoadMessage(arr, item, index, load) {
    arr[`${index}`].endTime = +new Date()
    arr[`${index}`].src = item.getAttribute('src')
    arr[`${index}`].index = index
    arr[`${index}`].loadTime = (arr[`${index}`].endTime - arr[`${index}`].startTime) + 'ms'
    arr[`${index}`].load = load 
    // console.log(arr)
    sumAdd()                
  }

  // 计数函数
  function sumAdd() {
    count++
    // 预留图片加载进度
    progress = Math.ceil(count/7*100);
    (progress>=100) ? 100 : progress
    // console.log(progress) 
    
    // 图片加载完成 向服务器上报
    if (count == arr.length) {
      message()
    }
  }

  // 向服务器发送当前页面的图片加载情况
  function message () {
    let imgObject = {
      url: location.href,
      count: count,
      loadArr: arr
    } 

    // 请求接口
    console.log(imgObject)
  }
  // console.timeEnd()      
}

向服务器回报:

  • (1)当前页面地址;
  • (2)图片张数;
  • (3)每张图片的加载情况;
{url: "https://m2.qschou.com/v8/glowwormPlan/guide.html?islogin=1&islogin=1", count: 4, loadArr: Array(4)}
count: 4
loadArr: Array(4)
0: {startTime: 1545284954692, endTime: 1545284954760, src: "https://static2.qschou.com/img/v8/glowwormPlan/guide/assets/g-head-bg.png", index: 0, loadTime: "68ms", …}
1: {startTime: 1545284954692, endTime: 1545284954781, src: "https://static2.qschou.com/img/v8/glowwormPlan/guide/assets/g-icon1.png", index: 1, loadTime: "89ms", …}
2: {startTime: 1545284954692, endTime: 1545284954784, src: "https://static2.qschou.com/img/v8/glowwormPlan/guide/assets/g-icon2.png", index: 2, loadTime: "92ms", …}
3: {startTime: 1545284954692, endTime: 1545284954795, src: "https://static2.qschou.com/img/v8/glowwormPlan/guide/assets/g-icon3.png", index: 3, loadTime: "103ms", …}
length: 4
__proto__: Array(0)
url: "https://m2.qschou.com/v8/glowwormPlan/guide.html?islogin=1&islogin=1"
__proto__: Object

发现新问题

看上去这样处理,好像可以得到,一个当前页面的所有图片的加载情况。实际上并没有拿到图片真正开始加载的时间。而且Date对象的方法都只能精确到毫秒级别(一秒的千分之一),想到得到精确的时间差别Date对象也是无能为力,无法知道图片加载的时间进度。

遇上performance

在ES5中有一个“高精度时间戳API”,部署在 performance 对象。它的精度可以达到微秒(1毫秒的千分之一)。

performance.getEntries() 带给我们的惊喜

浏览器在获取网页时,会对网页中每一个对象(脚本文件、样式表、图片文件等等)发出一个http请求。performance.getEntries方法以数组形式,返回这些请求的时间统计信息,有多少个请求,返回数组就会多少个成员。该方法只能在浏览器中使用。window.performance.getEntries(),返回一个高精度的时间戳对象,每个属性的单位是微秒(microsecond), 即百万分之一秒。

萤火虫计划攻略 页面上测试performance.getEntries()

performance.png

performance.getEntries()可以获取到所有资源的请求信息。我们需要过滤掉无用的资源信息,只保留图片。在过滤图片的

let arr = window.performance.getEntries()
let newArr = []

arr.forEach((item) => {
  if (item.initiatorType == 'img' && item.name.indexOf('https://hm.baidu.com') == -1 && item.name.indexOf('https://recevapi.qschou.com/dtas') == -1) {
    newArr.push(item)
  }
})

console.log(newArr) 

拿到所有图片的请求时间统计信息。取performance.getEntries()[0] 第一张图片的统计信息:

connectEnd: 0 // 返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳。如果建立的时持久连接,则返回值等同与fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。
connectStart: 0 // 返回http请求开始向服务器发送时的Unix毫秒时间戳。如果使用持久连接(persistent connection),则返回等同于fetchStart属性的值
decodedBodySize: 0 
domainLookupEnd: 0 //返回域名查询结束时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回值等同于fetchStart属性的值。
domainLookupStart: 0// 返回域名查询开始时的Unix毫秒时间戳。如果使用持久连接,或者信息是从本地缓存获取的,则返回等同与fetch属性的值。
duration: 0
encodedBodySize: 0
entryType: "resource"
fetchStart: 774.6000000042841//返回浏览器准备使用http请求读取文档时的Unix毫秒时间戳。该事件在网页查询本地缓存之前发生。
initiatorType: "img"
name: "https://static2.qschou.com/img/v8/glowwormPlan/guide/assets/g-head-bg.png"
nextHopProtocol: "http/1.1"
redirectEnd: 0 // 返回最后一个http跳转结束时的 unix毫秒时间戳。如果没有跳转,或者不是通一个域名内部的跳转,则返回值为0
redirectStart: 0 // 返回最后一个http跳转开始时的 unix毫秒时间戳。如果没有跳转,或者不是通一个域名内部的跳转,则返回值为0
requestStart: 0 // 返回浏览器向服务器发出http请求时(或从本地缓存读取)最后一个字节时的毫秒时间戳。
responseEnd: 774.6000000042841 // 返回浏览器从服务器收到最后一个字节时的毫秒时间戳
responseStart: 0
secureConnectionStart: 0//返回浏览器与服务器开始安全连接的握手时的毫秒时间戳。如果当前网页不需要安全连接,则返回0
serverTiming: []
startTime: 774.6000000042841
transferSize: 0
workerStart: 0

其中重要的是 duration、fetchStart、responseEnd、startTime,我们就知道图片的开始加载时间,结束加载时间,以及加载持续时间。

duration: 24.900000003981404 //加载持续时间

fetchStart: 570.2999999921303 //返回浏览器准备使用HTTP请求读取文档时的毫秒时间戳

responseEnd: 595.1999999961117 //返回浏览器从服务器收到最后一个字节时的毫秒时间戳

startTime: 570.2999999921303//开始时间加载时间

TODO List

背景图片的加载情况

封装成SDK

启node服务 创建数据库和表

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,241评论 4 61
  • 我为什么从读书会成员做到读书会投资人说到读书会,太多了。 高中的时候,那个时候互联网还不发达,在同桌的推荐下,我就...
    英吉阅读 1,290评论 4 20
  • 昨天的樊登读书会,我非常认真的听课,做笔记,我想记录他的每一句话,记录他表达出来的每一个观点,一方面练练自己的速记...
    早起的猫爱上学阅读 169评论 0 0
  • 麋鹿跑过第三排树木 我的森林便鲜活了起来 蓝色的猫头鹰蹲在榕树上 蜂鸟已归巢,鼹鼠又开辟了新的隧道 萤火虫点亮了夜...
    云中飘舞阅读 2,094评论 50 52
  • 江南多雨,偏偏那雨又很像南方人的性格,不急不躁,喜欢慢条斯理地下。就连顺着瓦棱落下的雨滴,也是平平仄仄的合着韵脚。...
    梁延峰阅读 580评论 0 1