gmail loading progress bar 实现原理

📅 2026/7/5 3:53:11
gmail loading progress bar 实现原理
Gmail 登陆时会显示一个progress bar 显示加载的进度。最先以为是模拟的效果但是仔细观察发现进度条是真实反映加载以及下载进度的并不依赖网络状况。所以非常好奇因为在javascript中缺少检测文档下载进度的ApIjs的安全机制也禁止这样做且只提供了加载开始加载中加载完成或加载错误等状态。那么gmail 是如何实现实时监控加载百分比的呢用firebug 监控 gmail登陆时的文件下载可以找到一个get请求该请求返回html文本文件大小为300多k在其中找到这样一个函数function _B_prog(pct){top[pr] pct;if (_B_thumbStyle_ undefined) {var thumb top.document.getElementById(lpt);_B_thumbStyle_ thumb ? thumb.style : null}if (_B_thumbStyle_) {_B_thumbStyle_.width Math.round(pct * 0.99) %;if (pct 100)_B_thumbStyle_ null}}该函数在html body 后定义。定义可知进度条由该函数动态实现。再来看后面大段大段的script标签标签中是压缩的js你可以在每一段script定义最末找到调用_B_prog(pct)的语句并且参数是从1一直到100如下所示scriptvar JS_START_TIME(new Date).getTime(),GLOBALStop.GLOBALS;if(o_6IqNZ5hNQ.zh_CN.!GLOBALS[4])top.location.replace(top.location.href.split(#)[0]);function _B_log(imp,opt_val){var pimpimp;if(arguments.length1)pvalopt_val;_B_logImg_(jsle,p)}var loadTimes[GLOBALS[0],GLOBALS[1],JS_START_TIME];function _B_record(){loadTimes.push((new Date).getTime())}var _B_thumbStyle_;function _B_prog(pct){top[pr]pct;if(_B_thumbStyle_undefined){var thumbtop.document.getElementById(lpt);_B_thumbStyle_thumb?thumb.style:null}if(_B_thumbStyle_){_B_thumbStyle_.widthMath.round(pct*0.99)%;if(pct100)_B_thumbStyle_null}}function _B_err(e){var stateloadTimes.join(-);_B_logImg_(jserr,jsstateencodeURIComponent(state)jsmsgencodeURIComponent(e));_B_handleError(e)}function _B_handleError(e){throw e;}function _B_logImg_(v,p){(new Image).src?ui2viewvpikGLOBALS[9]random(new Date).getTime()}window.onerrorfunction(message,url,line){_B_err(message)};_B_prog(1);/scriptscript....function Ala(b){var a[];if(b)for(;b.isValidRow();)a.push(b.field(0)),b.next();return a}function Bla(b){return bb.isValidRow()?b.field(0):l}function Cla(b){if(bb.isValidRow()){for(var a{},cb.fieldCount(),d0;dc;d)a[b.fieldName(d)]b.field(d);return a}else return l}function Dla(b){var a[];if(bb.isValidRow())for(var cb.fieldCount(),d0;dc;d)a[d]b.field(d);return a}function Ela(b,a,c,d){if(c.length0||dc.length)return b.execute(a);else{if(ka(c[d]))return b.execute(a,c[d]);cArray.prototype.slice.call(c,d);return b.execute(a,c)}}function Fla(b,a,c,d,e){bEla(b,a,d,e);try{return c(b)}finally{bb.close()}}function Gla(b,a){var c,d;ca?ROLLBACK:COMMIT;da?beforerollback:beforecommit;var eb.dispatchEvent(new yla(d));if(e)b.ia.execute(c),b.ka0,da?rollback:commit,b.dispatchEvent(new yla(d));return e}function ll(b){a:{var ab.nb;if(b.Ma)if(b.ka0){b.Ba!1;b.dispatchEvent(new yla(beforebegin));b.ia.execute(BEGIN a);b.ebHla[a];b.ka1;try{b.dispatchEvent(new yla(begin))}catch(c){b.ia.execute(ROLLBACK),b.ka0,h(c)}b!0;break a}else b.Ba?h(Error(106)):Hla[a]b.eb?h(Error(107)):b.ka;b!1}return b}function ml(b){if(b.Ma)if(b.ka0h(Error(108)),b.ka1){var aGla(b,b.Ba);return!b.Baa}else b.ka--;return!1}function Ila(){}function Jla(b,a){this.aab;this.eaa}function Kla(b){ri(this);this.Tab}var LlaGLOBALS[0],MlaGLOBALS[2],olGLOBALS[3],hfGLOBALS[4],NlaGLOBALS[5],plGLOBALS[6],qlGLOBALS[7],OlaGLOBALS[8],rlGLOBALS[9],slGLOBALS[10],PlaGLOBALS[11],QlaGLOBALS[12],RlaGLOBALS[14],tlGLOBALS[15],ulGLOBALS[16],SlaGLOBALS[17],TlaGLOBALS[18],vlGLOBALS[19],UlaGLOBALS[20],mjaGLOBALS[21],VlaGLOBALS[22],WlaGLOBALS[24],XlaGLOBALS[25],YlaGLOBALS[26],ZlaGLOBALS[27],amaGLOBALS[28],bmaGLOBALS[29],cmaGLOBALS[30];_B_prog(13)}catch(e){_B_err(e)}/script。。。一直到script...hL.prototype.eRfunction $cvb(a,c){var dthis.ha,e[];e[0]w().toString(16);e[2]0;e[18][a];e[24]c;enew Dr(^act,e);this.insertNode(mBa(d,e))};V(TLb,Er);TLb.prototype.aafunction $dvb(a,c){var dthis.Kn.Ua.ic();if(Zr(d)aiu){vr(this.Kn.qj());dthis.Kn.Ua;Jh(d);gra(d);dthis.Kn;wr(d.Fe);d.Ua.Sc.ea();try{for(var e1,f;fc[e];e){var gnew Dr(^act,f),imBa(d.Ua,g);d.Fe.Jb((new LC(g.Yr()[0])).dw());var kd.Fe,mi.get().Yr()[0][17];if(m)for(var q0,uj;um[q];q)k.cO(u[8])(fb(m,q),q--);d.Fe.insertNode(i)}d.Fe.Ba();d.aa!0}finally{if(d.Ua.Sc.aa(),fd.Fe,f.Sed)f.Sel}return!0}return!1};TLb.prototype.eafunction $evb(a){var cthis.Kn.Ua.ic();Zr(c)a0this.Kn.qj().dispatchEvent(Oe)};V(ULb,PAa);ULb.prototype.aafunction $fvb(){return Zr(this.Yi.ic())?new hL(this.Yi):l};V(VLb,HCa);VLb.prototype.eafunction $gvb(a,c){var da.getItem();c.yOd.Sh(^act)};VLb.prototype.aafunction $hvb(a){if(a.yO){var cnew S;a.yO?Uj({Kc:GV,title:Buzz},c):c.append(nbsp;);return c.toString()}};O(N.Ja(),t);R(N.Ja(),t);_B_prog(100)}catch(e){_B_err(e)}/script结果很明显进度条就是这样每加载一段js就调用进度函数来显示进度。但是等等通常加载html时并不是一段接着一段下载并加载而是等整个文件下载完成后再加载执行这样就没有实时监控下载进度的效果了。关键就是在这里gmail并没有使用静态资源供客户端下载而是通过类似servlet技术返回html。