Angular JS - 相互依赖地添加库

时间:2022-09-11 13:42:21

I found this thread How to handle multiple JS libraries with different loading times in Angular? which I am using to add d3.js to my header. I now have to add d3.legend.js aswell. How would I accomplish this in a callback-manner?

我找到了这个线程如何在Angular中处理具有不同加载时间的多个JS库?我用来将d3.js添加到我的标题中。我现在还要添加d3.legend.js。我将如何以回调方式完成此任务?

var d3js = angular.module('d3', []);

d3js.factory('d3Service', ['$document', '$q', '$rootScope', '$window',
    function($document, $q, $rootScope, $window) {
        var d = $q.defer();

        function onScriptLoad() {
            // Load client in the browser
            $rootScope.$apply(function() { d.resolve($window.d3); });
        }
        // Create a script tag with d3 as the source
        // and call our onScriptLoad callback when it
        // has been loaded

        var scriptTag = $document[0].createElement('script');
        scriptTag.type = 'text/javascript';
        scriptTag.async = true;
        scriptTag.src = 'lib/d3.v3.js';

        scriptTag.onreadystatechange = function () {
            if (this.readyState == 'complete') onScriptLoad();
        }

        scriptTag.onload = onScriptLoad;

        var s = $document[0].getElementsByTagName('body')[0];
        s.appendChild(scriptTag);

        //this is now where I have to add d3.legend.js which depends on the successful loading of d3.js.

        return {
            d3: function() { return d.promise; }
        };

    }]);

2 个解决方案

#1


1  

A cut-down version of the original idea:

原始想法的简化版本:

var app = angular.module('SomeApp', []);
app.factory('LibraryFactory', function () {
    var factory = {};

    factory.getD3 = function(callback) {
        if(!window.d3) {
            var script = document.createElement("script");
            script.src = "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.min.js";
            document.head.appendChild(script);
            script.onload = function() {
                callback(window.d3);
            };
        } else {
            callback(window.d3);
        }
    };

    factory.getD3Legend = function(callback) {
        if(!window.d3.legend) {
            //...ditto
        }
    };

    return factory;
});

And to use the factory (eg, in a controller) you can chain the calls:

要使用工厂(例如,在控制器中),您可以链接呼叫:

app.controller('SomeTrialCtrl', function ($scope, LibraryFactory) {

    LibraryFactory.getD3(function (d3) {
        LibraryFactory.getD3Legend(function (d3WithLegend) {
            // place code using the libraries here
        });
    });
});

Or in the case of d3.legend, the factory.getD3Legend function could call the getD3 function internally to keep things simpler. Like:

或者在d3.legend的情况下,factory.getD3Legend函数可以在内部调用getD3函数以使事情更简单。喜欢:

factory.getD3Legend = function(callback) {
    factory.getD3(function(d3) {
        if(!d3.legend) {
            //...ditto
        }
        callback(d3);
    }
};

That's the basic idea anyway. @aarosil's answer in the original post probably is more Angular-correct.

无论如何,这是基本的想法。 @ aarosil在原帖中的答案可能更具有角度正确性。

#2


0  

I just loop through the array of libraries that I need to add and add them one by one see code below:

我只是循环遍历我需要添加的库数组并逐个添加它们,请参阅下面的代码:

 var _libraries: [
     'scripts/d3.min.js',
     'scripts/moment.min.js'
 ]

 for (var i = 0, len = _libraries.length; i < len; i++) {
     var s = document.createElement('script');
     s.type = 'text/javascript';
     s.src = _libraries[i];

     document.body.appendChild(s);
 }

Hope this helps.

希望这可以帮助。

#1


1  

A cut-down version of the original idea:

原始想法的简化版本:

var app = angular.module('SomeApp', []);
app.factory('LibraryFactory', function () {
    var factory = {};

    factory.getD3 = function(callback) {
        if(!window.d3) {
            var script = document.createElement("script");
            script.src = "https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.min.js";
            document.head.appendChild(script);
            script.onload = function() {
                callback(window.d3);
            };
        } else {
            callback(window.d3);
        }
    };

    factory.getD3Legend = function(callback) {
        if(!window.d3.legend) {
            //...ditto
        }
    };

    return factory;
});

And to use the factory (eg, in a controller) you can chain the calls:

要使用工厂(例如,在控制器中),您可以链接呼叫:

app.controller('SomeTrialCtrl', function ($scope, LibraryFactory) {

    LibraryFactory.getD3(function (d3) {
        LibraryFactory.getD3Legend(function (d3WithLegend) {
            // place code using the libraries here
        });
    });
});

Or in the case of d3.legend, the factory.getD3Legend function could call the getD3 function internally to keep things simpler. Like:

或者在d3.legend的情况下,factory.getD3Legend函数可以在内部调用getD3函数以使事情更简单。喜欢:

factory.getD3Legend = function(callback) {
    factory.getD3(function(d3) {
        if(!d3.legend) {
            //...ditto
        }
        callback(d3);
    }
};

That's the basic idea anyway. @aarosil's answer in the original post probably is more Angular-correct.

无论如何,这是基本的想法。 @ aarosil在原帖中的答案可能更具有角度正确性。

#2


0  

I just loop through the array of libraries that I need to add and add them one by one see code below:

我只是循环遍历我需要添加的库数组并逐个添加它们,请参阅下面的代码:

 var _libraries: [
     'scripts/d3.min.js',
     'scripts/moment.min.js'
 ]

 for (var i = 0, len = _libraries.length; i < len; i++) {
     var s = document.createElement('script');
     s.type = 'text/javascript';
     s.src = _libraries[i];

     document.body.appendChild(s);
 }

Hope this helps.

希望这可以帮助。