这两周一直太忙,没有好好处理上上上周遇到的一个让我加班到凌晨的问题,这个问题是判断flash的加载。

之前的思路是让flash的人在制作flash的时候,加入了一个回调方法,该方法再会回调我页面的方法。

想象虽然很丰满,但是现实确很骨感,由于页面资源的加载顺序问题,如果flash是通过缓存读取得到的,那么flash便会先于我的脚本加载,这时便会出现flash调不到我定义的方法。但是由于功能的原因以及考虑页面的整洁性,我又不能将脚本放入到head中,最终的解决思路就是在head中加入一个script标签单独定义回调函数,然后再定义一个全局变量,用于判断flash是否已经回调我页面的方法。

所以我就想能不能自己去判断flash的加载问题,然后百度了以下,发现除了percentLoaded方法之外并没有什么好的办法,而且之前还以为percentLoaded是有兼容性问题的,但通过仔细的查找资料,我个人认为该方法存在的兼容性原因不在于浏览器,而在于用户电脑安装的flash player 插件的问题,另外不同浏览器对于object与embed标签支持的不同,更将这个差异性拉的更大,所以为了解决这个问题,我就用定时器不断的轮询检测,而且对于根本不支持percentLoaded的浏览器,我默认给了6秒的等待时间,超出6秒则不在检测flash的加载。

在写判断Flash加载的功能同时,我也顺便把图片、音频、视频加载的功能也添加进来,自己封装了一个loadRes的小组件。

loadRes 即 load Resources 的简写,用于判断资源的加载。

===============================================

最终通过我对自己电脑的测试,并没有发现明显的bug,测试的浏览器有:

  IE6 : 可能存在隐患。

  IE7 - IE8 : 正常

  IE9 - IE10 :可能会并行触发onreadystatechange 与 onload的(我个人感觉这个不是啥问题)

  IE11 - edge : 正常

  Chrome : 正常

  Opera 12 (最后一版基于persto内核) :正常

  Safari 5.1.7(win版) :正常

  Firefox : 正常

PS : 但是我的“第七感”,还是可以感觉到这个组件肯定是有问题的,但是受限于自身的实力也只能做到这样了,所以这里主要是抛砖引玉之用,希望各路大神能多多提点意见,或者优化之类的。感激不尽!!

=========================================

下面是具体的代码:

 /*
* +++++++++++++++++++++++++++++++++++++++++++++
* loadRes (load Resources) Component
* version 1.0
* author gtshen
* date 2016/8/27
* bug feedback 903050269 (QQ)
* +++++++++++++++++++++++++++++++++++++++++++++
*/ (function(root){
'use strict';
function loadRes(params){ this.fn = params.fn || null;
this.filter = params.filter || 'img'; // Filter
this.oImgs = document.images;
this.imgs = [];
this.count = 0;
this.curr = 0;
this.read(); } loadRes.prototype.read=function(){ var _this = this; if(/audio/.test(this.filter) && 'Audio' in window){
this.audio = document.getElementsByTagName('audio');
this.count+=this.audio.length; } if(/video/.test(this.filter) && 'Video' in window){
this.video = document.getElementsByTagName('video');
this.count+=this.video.length; } if(/flash/.test(this.filter)){
var embed = document.getElementsByTagName('embed'),
object = document.getElementsByTagName('object'),
flen = (embed.length >= object.length)? embed.length : object.length; this.count+=flen;
} var loadImgs = function(){ var imgReg = /url\(\"?(.*[\.jpg|\.png|\.bmp|\.jpeg])\"?\)/,
allElement = document.getElementsByTagName('*'); for(var i =0,l=allElement.length;i<l;i++){
_this.oImgs[i] && _this.imgs.push(_this.oImgs[i].src); var style = (window.getComputedStyle)?getComputedStyle(allElement[i],null)['backgroundImage'] : allElement[i].currentStyle['backgroundImage']; if(imgReg.test(style)){
_this.imgs.push(RegExp.$1);
}
}
_this.count+=_this.imgs.length; for(var i = 0,l=_this.imgs.length;i<l;i++){
var img = new Image();
img.src = _this.imgs[i];
if(img.complete){
_this.fn && _this.fn(_this.count,++_this.curr);
}else{
img.onload = function(){
if(!this.isloaded){
this.isloaded = true;
_this.fn && _this.fn(_this.count,++_this.curr);
}
};
img.onreadystatechange=function(){
if(_this.readyState == 'loaded' || _this.readyState == 'complete' && !this.isloaded){
this.isloaded = true;
_this.fn && _this.fn(_this.count,++_this.curr);
}
};
img.onerror=img.onabort=function(){
_this.onerror=_this.onabort=null;
_this.fn && _this.fn(_this.count,++_this.curr);
};
}
} }(); if(/audio/.test(this.filter) && 'Audio' in window){ var loadMusic=function(){ // Audio load handler
for(var i=0,l=_this.audio.length;i<l;i++){
_this.audio[i].onloadedmetadata=function(){
_this.fn && _this.fn(_this.count,++_this.curr);
};
_this.audio[i].onerror=function(){
_this.fn && _this.fn(_this.count,++_this.curr);
};
}
}(); } if(/video/.test(this.filter) && 'Video' in window){ var loadVideo=function(){ // Video load handler for(var i=0,l=_this.video.length;i<l;i++){
_this.video[i].onloadedmetadata=function(){
_this.fn && _this.fn(_this.count,++_this.curr);
};
_this.video[i].onerror=function(){
_this.fn && _this.fn(_this.count,++_this.curr);
};
} }();
} if(/flash/.test(this.filter)){ var loadFlash = function(){ // Flash Laded Handler var loaded = 0,
num = 0,
timer = null,
core = function(){
num++;
for(var i=0,l=flen;i<l;i++){
if(loaded < flen){
try{
try{
if(embed[i].PercentLoaded()){ if(Math.floor(embed[i].PercentLoaded()) == 100 && !embed[i].flag){
loaded++;
embed[i].flag = true;
_this.fn && _this.fn(_this.count,++_this.curr);
}
num = 0; }
}catch(a){ if(embed[i].PercentLoaded){
if(Math.floor(embed[i].PercentLoaded())== 100 && !embed[i].flag){
loaded++;
embed[i].flag = true;
_this.fn && _this.fn(_this.count,++_this.curr);
}
num = 0;
}
}
}catch(b){}
try{
try{
if(object[i].PercentLoaded()){
if(Math.floor(object[i].PercentLoaded())== 100 && !object[i].flag){
loaded++;
object[i].flag = true;
_this.fn && _this.fn(_this.count,++_this.curr);
}
num = 0;
}
}catch(c){
if(object[i].PercentLoaded){
if(Math.floor(object[i].PercentLoaded) == 100 && !object[i].flag){
loaded++;
object[i].flag = true;
_this.fn && _this.fn(_this.count,++_this.curr);
}
num = 0;
}
}
}catch(d){}
}
} if(loaded >= flen){
return false;
}
if(num >= flen){
_this.fn && _this.fn(_this.count,_this.curr+=num);
return false;
} timer = setTimeout(core,1000);
};
core();
}(); }
};
root.loadRes = function(params){
new loadRes(params);
};
})(window);

======= 调用方式 =======

 loadRes({
'filter':'img,flash,audio,video', //用于指定加载何种类型的资源,每种资源用逗号分隔。
'fn':function(total,cur){ // 资源加载的回调函数。total:要加载的资源总数,cur当前已完成加载的资源数量。
/*
if(cur >= total) {
Here is Your Code Area
}
*/
}
});

自己封装的一个LoadRes组件的更多相关文章

  1. 从零开始教你封装自己的vue组件

    组件(component)是vue.js最强大的功能之一,它可以实现功能的复用,以及对其他逻辑的解耦.但经过一段时间的使用,我发现自己并没有在业务中发挥出组件的最大价值.相信很多刚开始使用vue的朋友 ...

  2. 自己封装的一个JS分享组件

    因为工作的需求之前也封装过一个JS分享插件,集成了我们公司常用的几个分享平台. 但是总感觉之前的结构上很不理想,样式,行为揉成一起,心里想的做的完美,实际上总是很多的偏差,所以这次我对其进行了改版. ...

  3. Vue + Element-ui实现后台管理系统(4)---封装一个ECharts组件的一点思路

    封装一个ECharts组件的一点思路 有关后台管理系统之前写过三遍博客,看这篇之前最好先看下这三篇博客.另外这里只展示关键部分代码,项目代码放在github上: mall-manage-system ...

  4. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

    前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...

  5. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper

    前言:之前学习过很多的Bootstrap组件,博主就在脑海里构思:是否可以封装一套自己Bootstrap组件库呢.再加上看到MVC的Razor语法里面直接通过后台方法输出前端控件的方式,于是打算仿照H ...

  6. JS组件系列——封装自己的JS组件,你也可以

    前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...

  7. JS组件系列——分享自己封装的Bootstrap树形组件:jqTree

    前言:之前的一篇介绍了下如何封装自己的组件,这篇再次来体验下自己封装组件的乐趣.看过博主博客的园友应该记得之前分享过一篇树形菜单的使用JS组件系列——Bootstrap 树控件使用经验分享,这篇里面第 ...

  8. JS组件系列——封装自己的JS组件

    前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...

  9. 原生JS面向对象思想封装轮播图组件

    原生JS面向对象思想封装轮播图组件 在前端页面开发过程中,页面中的轮播图特效很常见,因此我就想封装一个自己的原生JS的轮播图组件.有了这个需求就开始着手准备了,代码当然是以简洁为目标,轮播图的各个功能 ...

随机推荐

  1. CYQ.Data 支持WPF相关的数据控件绑定(2013-08-09)

    事件的结果 经过多天的思考及忙碌的开发及测试,CYQ.Data 终于在UI上全面支持WPF,至此,CYQ.Data 已经可以方便支持wpf的开发,同时,框架仍保留最低.net framework2.0 ...

  2. 循序渐进做项目系列(5):制作安装包,谁人都可以!——VS制作安装包简明教程

    一开始让我做安装包的时候,其实我是拒绝的.因为我根本就不会做安装包.查了资料之后,我很懵,很晕,很乱,因为不清晰,不简明,不直白.然而经过一番彷徨的挣扎,我终于发现:制作安装包,谁人都可以!故挥狼毫, ...

  3. Nova PhoneGap框架 第五章 文件结构

    一个好的项目架构必然有着合理的文件结构,如果一个项目的文件组织混乱,那么可以断言一定是项目架构有问题. 合理的文件结构能够帮你更清晰的管理你的文件,并且当需要添加新的文件的时候,你的程序员很清楚应该加 ...

  4. 小型单文件NoSQL数据库SharpFileDB初步实现

    小型单文件NoSQL数据库SharpFileDB初步实现 我不是数据库方面的专家,不过还是想做一个小型的数据库,算是一种通过mission impossible进行学习锻炼的方式.我知道这是自不量力, ...

  5. 《Entity Framework 6 Recipes》中文翻译系列 (46) ------ 第八章 POCO之领域对象测试和仓储测试

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-8  测试领域对象 问题 你想为领域对象创建单元测试. 这主要用于,测试特定的数 ...

  6. css垂直居中那点事

    这是我技术博客生涯的第一篇文章,想想还是有点小鸡冻...菜鸟的征程现在要开始了 学习css的时候经常被各种问题纠结到不要不要的,没办法,只能写写博客帮助整理一下自己的思绪和帮助一下和我遇到同样问题的小 ...

  7. Android RatingBar 自定义样式

    Android RatingBar 自定义样式 1.先定义Style: <style name="RadingStyle" parent="@android:sty ...

  8. 自定义函数执行动态sql语句

    --函数中不能调用动态SQL,使用用存储过程吧.如果还要对函数做其他操作,换成存储过程不方便,可以考虑把其他操作一起封装在存储过程里面.如:   create proc [dbo].[FUN_YSCL ...

  9. PHP SESSION机制,从存储到读取

    PHP中,如果要获取SESSION数据,必须要有对应的session_id,session_id的获取方式有两种 1.基于客户端的cookie 2.基于url 先说第一种情况,基于客户端的cookie ...

  10. Sql Server系列:排序函数

    在SQL Server中有4个排序函数:ROW_NUMBER().RANK().DENSE_RANK()及NTILE()函数. 1. ROW_NUMBER()函数 ROW_NUMBER()函数为每条记 ...