Skip to content
This repository has been archived by the owner on Sep 15, 2021. It is now read-only.

Support loading multiple JavaScript files before calling back #39

Open
coopy opened this issue Jul 30, 2016 · 12 comments
Open

Support loading multiple JavaScript files before calling back #39

coopy opened this issue Jul 30, 2016 · 12 comments

Comments

@coopy
Copy link

coopy commented Jul 30, 2016

I'm considering using little-loader to dynamically load in component suites at run-time. Currently, there is only support for a singular src string. I would welcome support for an array of src strings, to load in multiple libraries. Is this in alignment with the roadmap?

@ryan-roemer
Copy link
Contributor

ryan-roemer commented Jul 30, 2016

@coopy -- We're aiming to keep little-loader razor thin. I think this is most appropriate for documentation / best practices around "patterns" captured in: #20

Extra pattern suggestions and documentation PRs most welcome!

Also, I'm open to examples (maybe in the test suite) we can add to.

For you here, here's a strawman pattern for parallel loading:

var load = window._lload; // or however required in...

var parallelLoad = function (libs, callback) {
  var finished = 0;
  var errs = [];

  if (!(libs && libs.length)) { return callback([]); }

  libs.forEach(function (lib) {
    load(lib, function (err) {
      // capture errors array and return all to callback.
      // Note: _Could_ do other logic to bail early when first error occurs.
      errs = errs.concat(err ? [err] : []); 

      finished++;
      if (finished === libs.length) {
        callback(errs);
      }
    });
  });
};

parallelLoad([
  "foo.js",
  "bar.js"
], function (errs) {
  console.log("ALL DONE!");
  console.log("Errors: " + errs);
});

And, here's a strawman pattern for sequential loading:

var load = window._lload; // or however required in...

var seriesLoad = function (libs, callback) {
  // Load function and recursively call next function.
  var loadLib = function (idx) {
    var lib = libs[idx];

    // Done with all libs.
    if (typeof lib === "undefined") {
      callback();
    }

    // Load this lib.
    load(lib, function (err) {
      // Short circuit if error.
      if (err) { return callback(err); }

      // Recursively go for next.
      loadLib(idx + 1);
    });
  }

  // Start at first lib index.
  loadLib(0);
};

seriesLoad([
  "foo.js",
  "bar.js"
], function (err) {
  console.log("ALL DONE!");
  console.log("Error: " + err);
});

@exogen
Copy link
Contributor

exogen commented Jul 30, 2016

I'm not against adding a helper for this at all, but the problem is that it muddies the waters a bit w.r.t. the main important feature of little-loader's callback: that it executes synchronously following the script's execution. Touting this benefit while allowing multiple scripts to be passed might make people think that all the loaded scripts are executed in one synchronous block along with the callback, when in reality other code would be allowed to run in between each script's execution.

I'm assuming you're just using little-loader because it's a nice & small script loader, and don't need our strong callback guarantees for the case of multiple scripts?

@ryan-roemer
Copy link
Contributor

@coopy @exogen -- I've updated by two patterns above. As you can see with even these simple scenarios, there is a lot of choice about how to handle errors / early termination / etc.

I am definitely up for documenting / explaining these patterns.

I'm potentially open to including them as separate includes as utilities...

@jknight12882
Copy link

jknight12882 commented Aug 16, 2016

What would be particularly great is if it were possible to download several files in parallel, but execute them in order. This does not seem possible with the current library, but would greatly help bootstrapping applications that have several external dependencies

@exogen
Copy link
Contributor

exogen commented Aug 16, 2016

@jknight12882: That's unfortunately not possible due to CORS – it's one reason why AMD was invented! :)

@jknight12882
Copy link

@exogen CORS has nothing to do with it. CORS deals with making ajax calls. You can load <scripts> from any domain. (see jsonp).

@jknight12882
Copy link

You could control evaluation order by not appending the script tags to the DOM until all the scripts have downloaded

@exogen
Copy link
Contributor

exogen commented Aug 16, 2016

@jknight12882: It does have to do with CORS, trust me. You can't get the content of scripts from other domains, which would be required for delaying their execution.

@jknight12882
Copy link

@exogen see my comment above about controlling evaluation order by waiting til all scripts have downloaded before appending them to the DOM.

@exogen
Copy link
Contributor

exogen commented Aug 16, 2016

You could control evaluation order by not appending the script tags to the DOM until all the scripts have downloaded

Try it and report back my friend – this is a well understood topic! :)

@jknight12882
Copy link

my mistake, it looks like the delayed appending to DOM was only for < IE10.

@exogen
Copy link
Contributor

exogen commented Aug 16, 2016

@jknight12882: True that, readyState would make it possible for old IE, but other browsers only have load, which is fired after execution. That's why you'd need AJAX + eval to do it on other browsers, but then, CORS.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

4 participants