天天看點

Sys.ScriptLoader與JS加載進度條的實作

 今天有人問我,163郵箱那樣的Javascript加載進度條是如何實作的。

我不知道,不過實作一個不難,因為<script />有onload和onreadystatechange。還有就是,我們有Atlas。

Atlas中有個類:Sys.ScriptLoader,它的作用就是在頁面中依次地加載多個Script檔案。在實作之前,先來分析一下這個類的代碼。

  1

Sys.ScriptLoader與JS加載進度條的實作

Sys.ScriptLoader = function() {

  2

Sys.ScriptLoader與JS加載進度條的實作

  3

Sys.ScriptLoader與JS加載進度條的實作

    // 所有Script的reference對象數組。

  4

Sys.ScriptLoader與JS加載進度條的實作

    var _references;

  5

Sys.ScriptLoader與JS加載進度條的實作

    // 所有Script加載完之後執行的回調函數。

  6

Sys.ScriptLoader與JS加載進度條的實作

    var _completionCallback;

  7

Sys.ScriptLoader與JS加載進度條的實作

    // 執行回調函數時提供的上下文(參數)。

  8

Sys.ScriptLoader與JS加載進度條的實作

    var _callbackContext;

  9

Sys.ScriptLoader與JS加載進度條的實作

 10

Sys.ScriptLoader與JS加載進度條的實作

    // 目前正在加載的Script的HTTP Element(<script />)。

 11

Sys.ScriptLoader與JS加載進度條的實作

    var _currentLoadingReference;

 12

Sys.ScriptLoader與JS加載進度條的實作

    // 目前的Script加載完成後所調用的回調函數。

 13

Sys.ScriptLoader與JS加載進度條的實作

    var _currentOnScriptLoad;

 14

Sys.ScriptLoader與JS加載進度條的實作

 15

Sys.ScriptLoader與JS加載進度條的實作

    // ScriptLoader唯一的方法,傳入三個參數,參數含義不再贅述。

 16

Sys.ScriptLoader與JS加載進度條的實作

    this.load = function(references, completionCallback, callbackContext) {

 17

Sys.ScriptLoader與JS加載進度條的實作

        _references = references;

 18

Sys.ScriptLoader與JS加載進度條的實作

        _completionCallback = completionCallback;

 19

Sys.ScriptLoader與JS加載進度條的實作

        _callbackContext = callbackContext;

 20

Sys.ScriptLoader與JS加載進度條的實作

 21

Sys.ScriptLoader與JS加載進度條的實作

        loadReferences();

 22

Sys.ScriptLoader與JS加載進度條的實作

    }

 23

Sys.ScriptLoader與JS加載進度條的實作

 24

Sys.ScriptLoader與JS加載進度條的實作

    // 開始加載引用。

 25

Sys.ScriptLoader與JS加載進度條的實作

    function loadReferences() {

 26

Sys.ScriptLoader與JS加載進度條的實作

        // 如果目前正在加載某個Script。

 27

Sys.ScriptLoader與JS加載進度條的實作

        // 這表示此方法不是第一次被調用,而是在某個Script被加載

 28

Sys.ScriptLoader與JS加載進度條的實作

        // 完成後才被調用,用以加載下一個Script。

 29

Sys.ScriptLoader與JS加載進度條的實作

        if (_currentLoadingReference) {

 30

Sys.ScriptLoader與JS加載進度條的實作

            // 檢視目前Script元素的readyState,IE下為complete,

 31

Sys.ScriptLoader與JS加載進度條的實作

            // 其他浏覽器如FF則為loaded(FF其實并無此屬性,

 32

Sys.ScriptLoader與JS加載進度條的實作

            // 但是下面的代碼會将其設為loaded)。

 33

Sys.ScriptLoader與JS加載進度條的實作

            // 如果加載失敗,則退出。

 34

Sys.ScriptLoader與JS加載進度條的實作

            if ((_currentLoadingReference.readyState != 'loaded') &&

 35

Sys.ScriptLoader與JS加載進度條的實作

                (_currentLoadingReference.readyState != 'complete')) {

 36

Sys.ScriptLoader與JS加載進度條的實作

                return;

 37

Sys.ScriptLoader與JS加載進度條的實作

            }

 38

Sys.ScriptLoader與JS加載進度條的實作

            else {

 39

Sys.ScriptLoader與JS加載進度條的實作

                // 進入此分支,表明加載成功。

 40

Sys.ScriptLoader與JS加載進度條的實作

 41

Sys.ScriptLoader與JS加載進度條的實作

                // 如果目前Script定義了onLoad函數。

 42

Sys.ScriptLoader與JS加載進度條的實作

                if (_currentOnScriptLoad) {

 43

Sys.ScriptLoader與JS加載進度條的實作

                    // 通過eval調用(這裡是個麻煩的地方)。

 44

Sys.ScriptLoader與JS加載進度條的實作

                    eval(_currentOnScriptLoad);

 45

Sys.ScriptLoader與JS加載進度條的實作

                    // 設為null,釋放資源。

 46

Sys.ScriptLoader與JS加載進度條的實作

                    _currentOnScriptLoad = null;

 47

Sys.ScriptLoader與JS加載進度條的實作

                }

 48

Sys.ScriptLoader與JS加載進度條的實作

 49

Sys.ScriptLoader與JS加載進度條的實作

                // 将相關事件設為null以確定釋放資源。

 50

Sys.ScriptLoader與JS加載進度條的實作

                if (Sys.Runtime.get_hostType() != Sys.HostType.InternetExplorer) {

 51

Sys.ScriptLoader與JS加載進度條的實作

                    // 如果目前浏覽器不是IE,見下面的代碼

 52

Sys.ScriptLoader與JS加載進度條的實作

                    // 會發現為<script />定義了onload事件。

 53

Sys.ScriptLoader與JS加載進度條的實作

                    _currentLoadingReference.onload = null;

 54

Sys.ScriptLoader與JS加載進度條的實作

 55

Sys.ScriptLoader與JS加載進度條的實作

                else {

 56

Sys.ScriptLoader與JS加載進度條的實作

                    // 如果是IE,見下面代碼會發現為了

 57

Sys.ScriptLoader與JS加載進度條的實作

                    // <script />定義了onreadystatechange事件。

 58

Sys.ScriptLoader與JS加載進度條的實作

                    _currentLoadingReference.onreadystatechange = null;

 59

Sys.ScriptLoader與JS加載進度條的實作

 60

Sys.ScriptLoader與JS加載進度條的實作

 61

Sys.ScriptLoader與JS加載進度條的實作

                // 最終釋放目前的<script />引用。

 62

Sys.ScriptLoader與JS加載進度條的實作

                _currentLoadingReference = null;

 63

Sys.ScriptLoader與JS加載進度條的實作

 64

Sys.ScriptLoader與JS加載進度條的實作

        }

 65

Sys.ScriptLoader與JS加載進度條的實作

 66

Sys.ScriptLoader與JS加載進度條的實作

        // 如果還有沒有加載的Script。

 67

Sys.ScriptLoader與JS加載進度條的實作

        if (_references.length) {

 68

Sys.ScriptLoader與JS加載進度條的實作

            // 出隊列。

 69

Sys.ScriptLoader與JS加載進度條的實作

            var reference = _references.dequeue();

 70

Sys.ScriptLoader與JS加載進度條的實作

            // 建立<script />

 71

Sys.ScriptLoader與JS加載進度條的實作

            var scriptElement = document.createElement('script');

 72

Sys.ScriptLoader與JS加載進度條的實作

            // 設目前的<script />和目前加載成功的回調函數。

 73

Sys.ScriptLoader與JS加載進度條的實作

            _currentLoadingReference = scriptElement;

 74

Sys.ScriptLoader與JS加載進度條的實作

            _currentOnScriptLoad = reference.onscriptload;

 75

Sys.ScriptLoader與JS加載進度條的實作

 76

Sys.ScriptLoader與JS加載進度條的實作

            if (Sys.Runtime.get_hostType() != Sys.HostType.InternetExplorer) {

 77

Sys.ScriptLoader與JS加載進度條的實作

                // 如果不是IE的話,那麼為<script />設屬性readyState,

 78

Sys.ScriptLoader與JS加載進度條的實作

                // 并且使用onload事件。

 79

Sys.ScriptLoader與JS加載進度條的實作

                scriptElement.readyState = 'loaded';

 80

Sys.ScriptLoader與JS加載進度條的實作

                scriptElement.onload = loadReferences;

 81

Sys.ScriptLoader與JS加載進度條的實作

 82

Sys.ScriptLoader與JS加載進度條的實作

 83

Sys.ScriptLoader與JS加載進度條的實作

                // 如果是IE,那麼使用onreadystatechange事件。

 84

Sys.ScriptLoader與JS加載進度條的實作

                scriptElement.onreadystatechange = loadReferences;

 85

Sys.ScriptLoader與JS加載進度條的實作

 86

Sys.ScriptLoader與JS加載進度條的實作

            scriptElement.type = 'text/javascript';

 87

Sys.ScriptLoader與JS加載進度條的實作

            scriptElement.src = reference.url;

 88

Sys.ScriptLoader與JS加載進度條的實作

 89

Sys.ScriptLoader與JS加載進度條的實作

            // 将<script />添加至DOM

 90

Sys.ScriptLoader與JS加載進度條的實作

            var headElement = document.getElementsByTagName('head')[0];

 91

Sys.ScriptLoader與JS加載進度條的實作

            headElement.appendChild(scriptElement);

 92

Sys.ScriptLoader與JS加載進度條的實作

 93

Sys.ScriptLoader與JS加載進度條的實作

            return;

 94

Sys.ScriptLoader與JS加載進度條的實作

 95

Sys.ScriptLoader與JS加載進度條的實作

 96

Sys.ScriptLoader與JS加載進度條的實作

        // 如果執行到這裡,說明所有的Script已經加載完了。

 97

Sys.ScriptLoader與JS加載進度條的實作

        // 如果定義了所有Script加載完之後執行的回調函數,

 98

Sys.ScriptLoader與JS加載進度條的實作

        // 那麼執行并釋放資源。

 99

Sys.ScriptLoader與JS加載進度條的實作

        if (_completionCallback) {

100

Sys.ScriptLoader與JS加載進度條的實作

            var completionCallback = _completionCallback;

101

Sys.ScriptLoader與JS加載進度條的實作

            var callbackContext = _callbackContext;

102

Sys.ScriptLoader與JS加載進度條的實作

103

Sys.ScriptLoader與JS加載進度條的實作

            _completionCallback = null;

104

Sys.ScriptLoader與JS加載進度條的實作

            _callbackContext = null;

105

Sys.ScriptLoader與JS加載進度條的實作

106

Sys.ScriptLoader與JS加載進度條的實作

            completionCallback(callbackContext);

107

Sys.ScriptLoader與JS加載進度條的實作

108

Sys.ScriptLoader與JS加載進度條的實作

109

Sys.ScriptLoader與JS加載進度條的實作

        _references = null;

110

Sys.ScriptLoader與JS加載進度條的實作

111

Sys.ScriptLoader與JS加載進度條的實作

}

112

Sys.ScriptLoader與JS加載進度條的實作

Sys.ScriptLoader.registerClass('Sys.ScriptLoader');

  可以看出,Sys.ScriptLoader加載script的方法就是通過代碼依次向<header />裡添加<script />元素。事實上,它在Atlas中被使用的非常少。

   事實上,Sys.ScriptLoader的代碼非常簡單,我添加的注釋越看越像畫蛇添足。值得注意的是所有的資源都被盡可能的釋放。尤其注意從第99 行開始的代碼,if體内首先用臨時變量保留兩個全局變量,然後再将全局變量釋放。其目的就是避免在completionCallback在執行時抛出異常 而導緻的記憶體洩露,即使隻有萬分之一的可能性。Javascript越多,則越容易造成記憶體洩露,在編寫JS代碼時最好注意這方面的問題。

接着解釋一下load方法的第一個參數references,原本以為這一個Sys.Reference類的數組,結果發現其實相差甚遠。不管怎麼樣順便看一下該類的代碼。

 1

Sys.ScriptLoader與JS加載進度條的實作

Sys.Reference = function() {

 2

Sys.ScriptLoader與JS加載進度條的實作

 3

Sys.ScriptLoader與JS加載進度條的實作

    var _component;

 4

Sys.ScriptLoader與JS加載進度條的實作

    var _onload;

 5

Sys.ScriptLoader與JS加載進度條的實作

 6

Sys.ScriptLoader與JS加載進度條的實作

    this.get_component = function() {

 7

Sys.ScriptLoader與JS加載進度條的實作

        return _component;

 8

Sys.ScriptLoader與JS加載進度條的實作

 9

Sys.ScriptLoader與JS加載進度條的實作

    this.set_component = function(value) {

10

Sys.ScriptLoader與JS加載進度條的實作

        _component = value;

11

Sys.ScriptLoader與JS加載進度條的實作

12

Sys.ScriptLoader與JS加載進度條的實作

13

Sys.ScriptLoader與JS加載進度條的實作

    this.get_onscriptload = function() {

14

Sys.ScriptLoader與JS加載進度條的實作

        return _onload;

15

Sys.ScriptLoader與JS加載進度條的實作

16

Sys.ScriptLoader與JS加載進度條的實作

    this.set_onscriptload = function(value) {

17

Sys.ScriptLoader與JS加載進度條的實作

        _onload = value;

18

Sys.ScriptLoader與JS加載進度條的實作

19

Sys.ScriptLoader與JS加載進度條的實作

20

Sys.ScriptLoader與JS加載進度條的實作

    this.dispose = function() {

21

Sys.ScriptLoader與JS加載進度條的實作

        _component = null;

22

Sys.ScriptLoader與JS加載進度條的實作

23

Sys.ScriptLoader與JS加載進度條的實作

24

Sys.ScriptLoader與JS加載進度條的實作

    this.getDescriptor = function() {

25

Sys.ScriptLoader與JS加載進度條的實作

        var td = new Sys.TypeDescriptor();

26

Sys.ScriptLoader與JS加載進度條的實作

27

Sys.ScriptLoader與JS加載進度條的實作

        td.addProperty('component', Object);

28

Sys.ScriptLoader與JS加載進度條的實作

        td.addProperty('onscriptload', String);

29

Sys.ScriptLoader與JS加載進度條的實作

        return td;

30

Sys.ScriptLoader與JS加載進度條的實作

31

Sys.ScriptLoader與JS加載進度條的實作

32

Sys.ScriptLoader與JS加載進度條的實作

Sys.Reference.registerSealedClass('Sys.Reference', null, Sys.ITypeDescriptorProvider, Sys.IDisposable);

33

Sys.ScriptLoader與JS加載進度條的實作

Sys.TypeDescriptor.addType('script', 'reference', Sys.Reference);

到這裡,我想大家也應該想到了如何使用Sys.ScriptLoader輕而易舉地制作JS加載的進度條。不過既然寫到了這裡,也就繼續把它進行一個簡單的實作。

首先是aspx檔案。

Sys.ScriptLoader與JS加載進度條的實作

<%@ Page Language="C#" %>

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

<script runat="server">

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

</script>

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

<html xmlns="http://www.w3.org/1999/xhtml" >

Sys.ScriptLoader與JS加載進度條的實作

<head runat="server">

Sys.ScriptLoader與JS加載進度條的實作

    <title>Load Scripts</title>

Sys.ScriptLoader與JS加載進度條的實作

    <script language="javascript">

Sys.ScriptLoader與JS加載進度條的實作

        function Load()

Sys.ScriptLoader與JS加載進度條的實作

        {

Sys.ScriptLoader與JS加載進度條的實作

            document.getElementById("bar").style.width = "0px";

Sys.ScriptLoader與JS加載進度條的實作

            var scripts = new Array();

Sys.ScriptLoader與JS加載進度條的實作

            for (var i = 0; i < 8; i++)

Sys.ScriptLoader與JS加載進度條的實作

            {

Sys.ScriptLoader與JS加載進度條的實作

                var s = new Object();

Sys.ScriptLoader與JS加載進度條的實作

                var sleep = Math.round((Math.random() * 400)) + 100;

Sys.ScriptLoader與JS加載進度條的實作

                s.url = "Script.ashx?sleep=" + sleep + "&t=" + Math.random();

Sys.ScriptLoader與JS加載進度條的實作

                s.cost = sleep;

Sys.ScriptLoader與JS加載進度條的實作

                scripts.push(s);

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

            Jeffz.Sample.LoadScripts.load(scripts);

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

    </script>

Sys.ScriptLoader與JS加載進度條的實作

</head>

Sys.ScriptLoader與JS加載進度條的實作

<body style="font-family: Arial;">

Sys.ScriptLoader與JS加載進度條的實作

    <form id="form1" runat="server">

Sys.ScriptLoader與JS加載進度條的實作

    <div>

Sys.ScriptLoader與JS加載進度條的實作

        <atlas:ScriptManager ID="ScriptManager1" runat="server">

34

Sys.ScriptLoader與JS加載進度條的實作

            <Scripts>

35

Sys.ScriptLoader與JS加載進度條的實作

                <atlas:ScriptReference Path="js/LoadScripts.js" />

36

Sys.ScriptLoader與JS加載進度條的實作

            </Scripts>

37

Sys.ScriptLoader與JS加載進度條的實作

        </atlas:ScriptManager>

38

Sys.ScriptLoader與JS加載進度條的實作

39

Sys.ScriptLoader與JS加載進度條的實作

        Progress Bar:        

40

Sys.ScriptLoader與JS加載進度條的實作

        <div style="border: solid 1px black;">

41

Sys.ScriptLoader與JS加載進度條的實作

            <div id="bar" style="height: 20px; width:0%; background-color:Red;"></div>

42

Sys.ScriptLoader與JS加載進度條的實作

        </div>

43

Sys.ScriptLoader與JS加載進度條的實作

        <input type="button" onclick="Load()" value="Load" />

44

Sys.ScriptLoader與JS加載進度條的實作

        <div id="message"></div>

45

Sys.ScriptLoader與JS加載進度條的實作

    </div>

46

Sys.ScriptLoader與JS加載進度條的實作

    </form>

47

Sys.ScriptLoader與JS加載進度條的實作

</body>

48

Sys.ScriptLoader與JS加載進度條的實作

</html>

  非常的簡單。使用兩個DIV制作了一個最簡單的進度條。在點選按鈕時調用了Load()函數。該函數随機生成了Script連結并生成了一個8元素的scripts數組。scripts數組的格式如下:

1

Sys.ScriptLoader與JS加載進度條的實作

var scripts = 

2

Sys.ScriptLoader與JS加載進度條的實作

[

3

Sys.ScriptLoader與JS加載進度條的實作

    { url : "[url]http://www.sample.com/sample1.js[/url]", cost : costOfLoading1 },

4

Sys.ScriptLoader與JS加載進度條的實作

    { url : "[url]http://www.sample.com/sample2.js[/url]", cost : costOfLoading2 },

5

Sys.ScriptLoader與JS加載進度條的實作

    { url : "[url]http://www.sample.com/sample3.js[/url]", cost : costOfLoading3 }

6

Sys.ScriptLoader與JS加載進度條的實作

];

  每個元素的url屬性不必說,而cost的功能就是表示加載該檔案所消耗的時間的 值。這個值沒有機關,用到的隻是這個值在總共消耗裡的比例。另外,可以看到有一個Script.ashx,其作用是模拟一個長時間script加載,它會 根據querystring中的sleep的值将線程休眠一段時間(至于後面的t,目的隻是通過改變querystring來避免點選按鈕時浏覽器的緩 存),這個檔案幾乎沒有代碼,可以在範例下載下傳中看到它的實作。最後通過調用Jeffz.Sample.LoadScripts.load方法進行加載,這 就涉及到了下面的代碼,LoadScripts.js:

Sys.ScriptLoader與JS加載進度條的實作

Type.registerNamespace('Jeffz.Sample');

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

Jeffz.Sample.LoadScripts = new function()

Sys.ScriptLoader與JS加載進度條的實作

{

Sys.ScriptLoader與JS加載進度條的實作

    var totalCost = 0;

Sys.ScriptLoader與JS加載進度條的實作

    var scriptLoader = new Sys.ScriptLoader();

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

    this.load = function(scripts)

Sys.ScriptLoader與JS加載進度條的實作

    {

Sys.ScriptLoader與JS加載進度條的實作

        if (Jeffz.Sample.__onScriptLoad != null)

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

            throw new Error("In progress");

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

        totalCost = 0;

Sys.ScriptLoader與JS加載進度條的實作

        Jeffz.Sample.__onScriptLoad = onScriptLoad;

Sys.ScriptLoader與JS加載進度條的實作

        var references = new Array();

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

        var loadedCost = 0;

Sys.ScriptLoader與JS加載進度條的實作

        for (var i = 0; i < scripts.length; i++)

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

            totalCost += scripts[i].cost;

Sys.ScriptLoader與JS加載進度條的實作

            loadedCost += scripts[i].cost;

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

            var ref = createReference(scripts[i].url, loadedCost);

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

            references.push(ref);

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

        scriptLoader.load(references, onComplete);

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

    function createReference(url, loadedCost)

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

        var ref = new Object();

Sys.ScriptLoader與JS加載進度條的實作

        ref.url = url;

Sys.ScriptLoader與JS加載進度條的實作

        ref.onscriptload = "Jeffz.Sample.__onScriptLoad('" + url + "', " + loadedCost + ")";

Sys.ScriptLoader與JS加載進度條的實作

        return ref;

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

    function onComplete()

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

        Jeffz.Sample.__onScriptLoad = null;

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

    function onScriptLoad(url, loadedCost)

Sys.ScriptLoader與JS加載進度條的實作
Sys.ScriptLoader與JS加載進度條的實作

        var progress = 100.0 * loadedCost / totalCost;

49

Sys.ScriptLoader與JS加載進度條的實作

        document.getElementById("bar").style.width = progress + "%";

50

Sys.ScriptLoader與JS加載進度條的實作

        document.getElementById("message").innerHTML += ("<strong>" + url + "</strong>" + " loaded.<br />");

51

Sys.ScriptLoader與JS加載進度條的實作

52

Sys.ScriptLoader與JS加載進度條的實作

   不過事情到此為止了嗎?事實上,我對這個Solution不怎麼滿意,雖然對于大多數情況應該已經夠用了。可以注意到,我将 Jeffz.Sample.LoadScripts實作成為了一個Singleton,也就是說,沒有另外一個和它一樣的執行個體。并且在load方法的一開 始就判斷是不是正在加載,如果是,那麼會抛出一個異常。實作了這麼一種“單線程”的加載,直接原因是受限于Sys.ScriptLoader的實作。

   請看Sys.ScriptLoader代碼的第44行,它使用了eval來“邪惡”地進行了script加載完成時的回調。這其實對于開發人員是一種非 常難受的實作,因為eval,是以無法地将一個函數的引用作為回調函數來傳遞。唯一能做的就是隻能把“根代碼”作為字元串形式來交給 Sys.ScriptLoader。雖然還是能夠通過Sys.ScriptLoader實作“并發”的Script加載(說白了最多像 Sys.ScriptLoader一樣建一個隊列嘛),但是代碼量自然而然就上去了,開發的複雜度也提高了。

  另外,Sys.ScriptLoader在加載某Script出錯時也沒有提示,而是直接退出,這個也不是很理想。

  不過我認為,這種“單線程”的script加載已經足夠用于大多數情況了。而且如果真的有“特殊”要求,參照Sys.ScriptLoader這個如此清晰明了的範例,自己重新寫一個對于廣大開發人員來說,難道還不是易如反掌的事情嗎?

本文轉自 jeffz 51CTO部落格,原文連結:http://blog.51cto.com/jeffz/60960,如需轉載請自行聯系原作者

繼續閱讀