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

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

我的问题一:不爱思考

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

培养思维

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

修炼内功

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

如何监听当前页面上的所有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服务 创建数据库和表

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

推荐阅读更多精彩内容

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