找回密码
 注册
搜索
热搜: 回贴

ASP.net:Sys.ScriptLoader与JS加载进度条的实现

2009-12-13 12:43| 发布者: admin| 查看: 54| 评论: 0|原作者: 琴姬

○今天有人问我,163邮箱那样的Javas......


  今天有人问我,163邮箱那样的Javascript加载进度条是如何实现的。
  我不知道,不过实现一个不难,因为
8
9
10
11 Load Scripts
12
29
30
31

32

33
34
35
36

37

38
39 Progress Bar:
40

41

42

43
44

45

46

47
48
  非常的简单。使用两个DIV制作了一个最简单的进度条。在点击按钮时调用了Load()函数。该函数随机生成了Script链接并生成了一个8元素的scripts数组。scripts数组的格式如下:
1var scripts =
2[
3 { url : "http://www.sample.com/sample1.js", cost : costOfLoading1 },
4 { url : "http://www.sample.com/sample2.js", cost : costOfLoading2 },
5 { url : "http://www.sample.com/sample3.js", cost : costOfLoading3 }
6];
  每个元素的url属性不必说,而cost的功能就是表示加载该文件所消耗的时间的值。这个值没有单位,用到的只是这个值在总共消耗里的比例。另外,可以看到有一个Script.ashx,其作用是模拟一个长时间script加载,它会根据querystring中的sleep的值将线程休眠一段时间(至于后面的t,目的只是通过改变querystring来避免点击按钮时浏览器的缓存),这个文件几乎没有代码,可以在范例下载中看到它的实现。最后通过调用Jeffz.Sample.LoadScripts.load方法进行加载,这就涉及到了下面的代码,LoadScripts.js:
1Type.registerNamespace('Jeffz.Sample');
2
3Jeffz.Sample.LoadScripts = new function()
4{
5 var totalCost = 0;
6 var scriptLoader = new Sys.ScriptLoader();
7
8 this.load = function(scripts)
9 {
10 if (Jeffz.Sample.__onScriptLoad != null)
11 {
12 throw new Error("In progress");
13 }
14
15 totalCost = 0;
16 Jeffz.Sample.__onScriptLoad = onScriptLoad;
17 var references = new Array();
18
19 var loadedCost = 0;
20 for (var i = 0; i < scripts.length; i++)
21 {
22 totalCost += scripts[i].cost;
23 loadedCost += scripts[i].cost;
24
25 var ref = createReference(scripts[i].url, loadedCost);
26
27 references.push(ref);
28 }
29
30 scriptLoader.load(references, onComplete);
31 }
32
33 function createReference(url, loadedCost)
34 {
35 var ref = new Object();
36 ref.url = url;
37 ref.onscriptload = "Jeffz.Sample.__onScriptLoad('" + url + "', " + loadedCost + ")";
38 return ref;
39 }
40
41 function onComplete()
42 {
43 Jeffz.Sample.__onScriptLoad = null;
44 }
45
46 function onScriptLoad(url, loadedCost)
47 {
48 var progress = 100.0 * loadedCost / totalCost;
49 document.getElementById("bar").style.width = progress + "%";
50 document.getElementById("message").innerHTML += ("" + url + "" + " loaded.
");
51 }
52}
  哎,似乎完全没有必要对代码进行多余的解释。到目前为止,一个简单的Script加载进度条就完成了,相当的简单。代码可以点击这里下载,也可以点击这里查看效果。
  不过事情到此为止了吗?事实上,我对这个Solution不怎么满意,虽然对于大多数情况应该已经够用了。可以注意到,我将Jeffz.Sample.LoadScripts实现成为了一个Singleton,也就是说,没有另外一个和它一样的实例。并且在load方法的一开始就判断是不是正在加载,如果是,那么会抛出一个异常。实现了这么一种“单线程”的加载,直接原因是受限于Sys.ScriptLoader的实现。
  请看Sys.ScriptLoader代码的第44行,它使用了eval来“邪恶”地进行了script加载完成时的回调。这其实对于开发人员是一种非常难受的实现,因为eval,所以无法地将一个函数的引用作为回调函数来传递。唯一能做的就是只能把“根代码”作为字符串形式来交给Sys.ScriptLoader。虽然还是能够通过Sys.ScriptLoader实现“并发”的Script加载(说白了最多像Sys.ScriptLoader一样建一个队列嘛),但是代码量自然而然就上去了,开发的复杂度也提高了。
  不过我认为,这种“单线程”的script加载已经足够用于大多数情况了。而且如果真的有“特殊”要求,参照Sys.ScriptLoader这个如此清晰明了的范例,自己重新写一个对于广大开发人员来说,难道还不是易如反掌的事情吗?

最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-29 21:23 , Processed in 0.238777 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部