简体   繁体   中英

Dynamically Included Javascript and Dependencies

So, as a sort of exercise for myself, I'm writing a little async script loader utility (think require.js, head.js, yepnope.js), and have run across a little bit of a conundrum. First, the basic syntax is like this:

using("Models/SomeModel", function() {
  //callback when all dependencies loaded
});

Now, I want to know, when this call is made, what file I'm in. I could do it with an ajax call, so that I can mark a flag after the content loads, but before I eval it to mark that all using calls are going to be for a specific file, then unset the flag immediately after the eval (I know eval is evil, but in this case it's javascript in the first place, not json, so it's not AS evil). I'm pretty sure this would get what I need, however I would prefer to do this with a script tag for a few reasons:

  1. It's semantically more correct
  2. Easier to find scripts for debugging (unique file names are much easier to look through than anonymous script blocks and debugger statements)
  3. Cross-domain requests. I know I could try to use XDomainRequest, but most servers aren't going to be set up for that, and I want the ability to reference external scripts on CDN's.

I tried something that almost got me what I needed. I keep a list of every time using is called. When one of the scripts loads, I take any of those using references and incorporate them into the correct object for the file that just loaded, and clear the global list. This actually seems to work alright in Firefox and Chrome, but fails in IE because the load events seem to go off at weird times (a jQuery reference swallowed a reference to another type and ended up showing it as a dependency). I thought I could latch on to the "interactive" readystate, but it doesn't appear to ever happen.

So now I come asking if anybody here has any thoughts on this. If y'all want, I can post the code, but it's still very messy and probably hard to read.

Edit: Additional usages

//aliasing and multiple dependencies
using.alias("ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js", "jQuery");

using(["jQuery", "Models/SomeModel"], function() {
  //should run after both jQuery and SomeModel have been loaded and run
});

//css and conditionals (using some non-existant variables here)
using.css({ src: "IEFix", conditionally: browser === "MSIE" && version < 9 });
//should include the IEFix.css file if the browser is IE8 or below

and to expound more on my response below, consider this to be file A (and consider the jquery alias from before to be there still):

using(["jQuery", "B"], function() {
  console.log("This should be last (after both jQuery and B have loaded)");
  console.log(typeof($));
});

Then this would be B:

using("C", function() {
  console.log("This should be second");
});

And finally, C:

console.log("This should be first");

The output should be:

This should be first
This should be second
This should be last (after both jQuery and B have loaded)
[Object Object]

Commendable that you are taking on such an educational project.

However, you won't be able to pull it off quite the way you want to do it.

The good news is:

  • No need to know what file you are in
  • No need to mess with eval.

You actually have everything you need right there: A function reference. A callback , if you will.

A rough P-code for your using function would be:

function using(modules, callback) {

  var loadedModules = []
  // This will be an ajax call to load things, several different ways to do it..
  loadedModules[0] = loadModule(modules[0]);
  loadedModules[1] = loadModule(modules[1]);

  // Great, now we have all the modules
  // null = value for `this`
  callback.apply(null,   loadedModules);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM