Javascript dependency solution with arbitrary orde

2019-07-14 05:42发布

问题:

The problem is this, I include a script, it uses another one, but what if that dependency also needs another script to be ready ? Which means loading it is not enough, but I also need to be sure its callback for initialization has been called before executing. The order of script tags in DOM can not be correct if the dependencies are allowed to require more dependencies and manifest them when them after being loaded.

The problems gets more complex when scripts and dependencies require more than one dependency, or a file satisfies more than one component.

Using.js seems to have a good approach for this, but first, the dependency relations should be known before they are being loaded, second the author states that some tests are not working anymore on Firefox. I suspect it is the blocking the execution thing, which seems a bit magical.

I have written a loader to handle this, completely asynchronous, which actually seems to be work. But I can not shake the gut feeling of doing something has been solved before, or can not be that complex.

回答1:

The order of script tags in DOM can not be correct if the dependencies are allowed to require more dependencies and manifest them after being loaded.

Well, what are these scripts that try to load their own dependencies, exactly? This is not a standard feature of JavaScript, so there is not one answer; how you cope with it is specific to the script that tries to include dependencies.

For synchronously loaded scripts (included via document.write or adding script elements to the DOM at load-time) you can at least be sure that you're good to go onload. For asynchronous loading (deferred scripts, AJAX inclusion, or ready-callbacks fired by timeout) there has to be a callback mechanism. If you are mixing various scripts that have different dependency and ready-callback systems, that's going to be a pain.

I have written a loader to handle this, completely asynchronous, which actually seems to be work. But I can not shake the gut feeling of doing something has been solved before, or can not be that complex.

No, not really. Dependency handling and dynamic script insertion are always going to be a little bit complicated. The only ‘solved’, standard approach is completely static scripts, writing them in dependency order manually.



回答2:

There are several approaches to solve your problem almost all approaches are in this Javascript Dependency Management presentation.

The one that better solves your problem is using jingo library.

Basically with jingo¹ you can do something like this to declare a module with dependencies:

  jingo.declare({
    require: [
      'hallmart.Greeter'
    ],
    name: 'hallmart.Store',
    as: function() {
      hallmart.Store = function() {
        var greeter = new hallmart.Greeter();
        this.admit = function(customer) {
          greeter.welcome(customer.name);
        };
      };
   }
 });

See code.google.com/p/jingo/wiki/GettingStarted for references.

¹ code.google.com/p/jingo/



回答3:

I'm biased but I recently created a javascript dependency manager called Pyramid. It seems similar to other dependency managers (and is probably similar to the one you created) except for a few key features.

  1. It can load any file, not just javascript and let's you define how the file is included in your web page. During development, I use it to load not just my javascript and css files but also insert html into my main page. This lets me store my html views separately (which is great for libraries like knockout)
  2. Combines your files when it is time for a release.
  3. Written entirely in javascript so setup is simple. You don't need to worry about external tools.
  4. You only have to set the include script for all your html files once. After that, all files can be updated in a single dependency loader file (rather than having to constantly update the include files in all the headers when scripts are renamed, removed, or added)

Pyramid Dependency Manager documentation

Some sample code to show how it works during development.

File: dependencyLoader.js

//Set up file dependencies
Pyramid.createOrUpdate({
    name: 'standard',
    files: [
    'standardResources/jquery.1.6.1.min.js'
    ]
});

Pyramid.createOrUpdate({
name:'lookAndFeel',
files: [
    'styles.css',
    'customStyles.css'
    ]
});

Pyramid.createOrUpdate({
name:'main',
files: [
    'createNamespace.js',
    'views/buttonView.view', //contains just html code for a jquery.tmpl template
    'models/person.js',
    'init.js'
    ],
    dependencies: ['standard','lookAndFeel']
});

Html Files

<head>
    <script src="standardResources/pyramid-1.0.1.js"></script>
    <script src="dependencyLoader.js"></script>
    <script type="text/javascript">
        Pyramid.load('main');
    </script>
</head>