How to handle multiple JS libraries with different loading times in Angular?

前端 未结 3 1283
渐次进展
渐次进展 2021-01-23 15:13

I am just learning Angular and I have some questions regarding the architecture of my app.

The project I will be working on will be using allot of external libraries: jQ

3条回答
  •  时光取名叫无心
    2021-01-23 15:49

    You can create a factory to load the external library you need. Return a deferred object for the library's script after it loads. Here is one I used for d3 library:

    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);
    
            return {
                d3: function() { return d.promise; }
            };
    
        }]);
    

    then in your directive, use then function of the deferred to wait until it's ready

    d3Service.d3().then(function(d3) {
        // place code using d3 library here
    }
    

    If your directive is needing access to multiple libraries, you can chain the deferreds.

    d3Service.d3().then(function(d3) {
        someOtherLibSvc.getLib().then(function(lib){
            // place code using d3 library and someOtherLibrary here
        }
    }
    

    To avoid this chaining check out bluebird and use Promise.join, Angular comes with $q automatically so I just used that here.

    Note: if you just load JQuery before angular, then angular.element will already reference JQuery. So you don't need to do this for JQuery, just load it in your main html page before Angular

提交回复
热议问题