接上篇。ie下错位几率相对而言有些大,于是基于interactive特性进行改善。这其实反而是走回老路了~
在意想之中的是,ie下十万分之一几率的错位果然降了,而且降到了没有一个错误……webkit内核依旧保持极低概率,奇怪的是firefox在上两次中从未出现错误的先提下,这次爆出了十位数的错位。
ie6
“BbAa” “162339″
“Aa” “858130″
“Bb” “859823″
“AaBb” “1551704″
ie7
“BbAa” “40125″
“Aa” “208591″
“Bb” “208680″
“AaBb” “376486″
ie8
“BbAa” “113878″
“Bb” “622694″
“Aa” “625345″
“AaBb” “1131155″
ie9
“BbAa” “24716″
“Aa” “113455″
“Bb” “113505″
“AaBb” “201967″
ie10
“BbAa” “1″
“BbAa” “8″
“Aa” “25″
“Bb”…
接上篇。尽管已经降到了十万分之一级别的几率,但并发下浏览器的不靠谱行为依旧存在。IE6-8下依旧为主要因素,这与使用者人数多也有关,基数大所以数量高。另外2次幂延迟算法对于单线程情况(aA)是能够完全纠正的,这点值得欣慰。
并发时,abAB、aABb、aAbB、ABba、abBA、AbBa、aBbA、aBAb几种情况按几率依次递减,想要完美解决必须全部纠正。在2次幂延迟算法纠正后,前面3个已经正确,但后面的还是错误的,它们可以统一概括为:ABba。结果原本应该赋给A的a跑到B的身上,互相错位了,所以要进行错位交换。
理论上前期不可能再进行处理了,我耗了很久发现前期处理是个悖论,剩下的可能只有运行时决定。
在运行时:
use(['a', 'b'], function(a, b) {
a.methodA();
b.methodB();
});
在错位情况下,a不具有methodA方法b才具有,b也反之。此时会抛异常。简单的做法是运行时try,捕捉到异常后交换错位的arguments再运行一次。看起来似乎不错,实际陷阱重重。
首先methodA和methodB可能方法名相同,甚至逻辑极为相似。这样就不会异常但运行结果是错的。这个概率很低。
然后这是在2个参数的情况下,2个以上排列比例太多,交换次数很恐怖,不切实际。
还有这只有1级递归,也就是a和b互相颠倒而已。如果a有依赖或b有依赖,所造成的错位可能有很多,那它们之间互相递归交换非常恐怖,根本不可能实现。
即使可以通过的define进行包裹一层,抽出factory返回的方法名来提升判断callback的参数顺序准确度,但依然不能解决上述所有问题。所以最后错位交换算法被pass。
IE下,通过getInteractiveScript的方法,可能提升并发准确度到百万分之一的级别,有待验证。
接上篇,之前用的加载script机制有问题,同时赋予了onload = onreadystatechange,这在同时支持的浏览器(ie9)下有影响,新的方法分开对待。
other success
BAba 1
Bb 1
BbAa 1
AaBb 1
BbAa 1
BAba 1
BbAa 1
Aa 2
AaBb 2
Bb 3
Aa 3
BAba 4
ABab 4
Aa 6
BbAa 6
ABab 6
Bb 8
ABab 12
AaBb 17
Bb 23
AaBb 26
ABab 30
Aa 32
Aa 76
Bb 102
ABab 155
ie7 success
ab 1
bAa 1
a 1
BaAb 61
ABba 83
BAba 12481
BbAa 26430
AaBb 69314
Aa 201493
Bb 202091
ABab 295501
ie6 success
aBb 1
AbBa 22
BAab 89
BAba 50511
BbAa 106465
AaBb 287284
Bb 835892
Aa 836129
ABab 1227774
webkit success
ABba 2
BaAb 7
BbAa 51452
Bb 254856
Aa 255189
AaBb 454364
FF success
BAba 2
ABab 109
BbAa 5512
Bb 35757
Aa 36034
AaBb 65577
ie10 success
BbAa 4
BAba 7
AaBb 12
Bb 35
Aa 45
ABab 59
opera success
ABab 6
Bb 3077
Aa 3092
AaBb 5990
ie9 success
BaAb 8
AbBa 8
BbAa 7968
BAba 17482
AaBb 26081
Bb 109073
Aa 109478
ABab 166921
ie8 success
AbBa 16
BAab 80
BAba 31761
BbAa 84319
AaBb 241514
Bb 616614
Aa 617047
ABab 874323
出现了onload抢先exec的现象且顺序不一致,比如 CcaABb,总数:123
B 1
BaAb 7
BaAb 8
AbBa 8
AbBa 16
AbBa 22
BaAb 61
顺序不一致,比如 CcAbBa,总数:381
ab 1
aBb 1
B 1
bAa 1
a 1
ABba 2
BaAb 7
BaAb 8
AbBa 8
AbBa 16
AbBa 22
BaAb 61
BAab 80
ABba 83
BAab 89
几率381/8226030 =0.000046316388342857974,主要集中在IE6-IE8。
接上篇。另外对于基础性原理不清楚的请查看射雕的介绍:http://lifesinger.wordpress.com/2011/11/11/get-url-in-module-loader/
通过1周的海量数据多次测试与研究,我和射雕发现了所有浏览器下都有的共同bug:onload事件先于script标签的加载发生。这个结论直接表明,目前所有对于script的onload的侦听都不是完美的!一旦有了这个低几率问题,那些莫名的错误会让人十分困惑。
介于此,我尝试使用2^ delay的算法来延迟onload的运行。它的理论基础来源于抑制网络风暴的算法:即onload先检查script的exec,没有时延迟2 ^ 0单位时间后再检查、再没有延迟2 ^ 1、2 ^ 2……以此类推。
在昨天的海量观测数据下面,结果是惊喜的。没有1次发生了error,全部正确。但是依然存在低几率次序打乱的情况,这是接下来要着手解决的问题(或者干脆忽略掉)。
最后祝福下Firefox和IE10,你们的顺序是100%正确的。
other success
AaBb 1
BbAa 1
Aa 1
AaBb 1
Bb 1
BAba 1
ABab 1
BbAa 1
BAba 1
ABab 1
Aa 1
AaBb 2
BbAa 3
Aa 3
BAba 3
Bb 4
Aa 5
BbAa 8
ABab 11
Bb 12
ABab 23
AaBb 23
Aa 26
AaBb 28
Bb 28
Aa 91
Bb 97
ABab 171
opera success
BbAa 1
BAab 1
ABba 1
BaAb 1
ABab 28
Bb 2742
Aa 2783
AaBb 5484
ie8 success
ABba 2
AbBa 8
BAab 17
BaAb 29
BAba 30901
BbAa 82405
AaBb 233970
Bb 599658
Aa 600632
ABab 853122
webkit success
ABba 2
BAab 2
BaAb 4
AbBa 5
BbAa 50606
Aa 246173
Bb 246419
AaBb 441956
ie10 success
BAba 2
AaBb 8
BbAa 9
Aa 29
Bb 31
ABab 36
ie9 success
AbBa 2
BaAb 4
BAab 30
ABba 159
BAba 8915
BbAa 15603
AaBb 35080
Aa 104627
Bb 105027
ABab 149314
ie7 success
AbBa 8
BaAb 12
BAab 35
ABba 81
BAba 11900
BbAa 25614
AaBb 66317
Aa 193519
Bb 193970
ABab 282723
ie6 success
ABba 10
AbBa 14
BAab 21
BaAb 57
BAba 50272
BbAa 104528
AaBb 275505
Bb 811928
Aa 813622
ABab 1189557
FF success
ABab 90
BbAa 5578
Bb 34745
Aa 34866
AaBb 63339
问题的起源是这样的:
假设加载有2个脚本A和B,而a和b则是附加在各自脚本上的onload侦听。众所周知的,IE下A加载完成exec后a并不是保证立刻触发的,非IE下正常。但是,倘若前提是A的加载完成和B的加载完成顺序确定,即A->B,那么a->b的顺序能不能得到保证?即:有可能是AaBb、ABab,但绝不可能有ABba。
自己测是发现不了问题,但显然范围太小不足以说明情况,所以我借助土豆的某个次要页面流量,做了个大范围精度测试。
目标:测出IE6、7、8、9下面的顺序情况。
理由:懂的入。
用例:用户有25%的几率加载a.js、25%的几率加载b.js、剩余50%全部加载,以此模拟出各种可能被缓存的情况——即可能先缓存a,然后再加载a和b。
数据结构:第一位的0和1标明页面是否发生error,是的话1,否的话0;后面大写字母是script标签被加载exec时记录,小写字母是其onload触发时记录;再后面数字是次数。
结果:近千万份数据,可能因对浏览器ua的判断稍稍有些误差。
error
ie6
“1Aab” “3410″
“1a” “2979″
“1b” “2901″
“1Bba” “1575″
“1Bab” “136″
“1Aba” “61″
“1″ “56″
“1Aa” “12″
“1A” “10″
“1ab” “9″
“1Bb” “7″
“1ABab” “4″
“1AB” “1″
ie7
“1b” “771″
“1a” “743″
“1Aab” “738″
“1Bba” “376″
“1″ “108″
“1Bab” “23″
“1Aba”…

本博客所有文章均采用