Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested/Hierarchy of head.js calls in multiples files doesn't work #231

Closed
jpmckinney opened this issue Apr 14, 2013 · 12 comments
Closed

Nested/Hierarchy of head.js calls in multiples files doesn't work #231

jpmckinney opened this issue Apr 14, 2013 · 12 comments

Comments

@jpmckinney
Copy link

See http://jsfiddle.net/TWDy4/ for a simple example of the bug. Here's the situation:

  1. I use headjs in my app to load dependencies. Once dependencies are loaded, I run my code, using headjs' callback.
  2. My dependencies use headjs to load their dependencies. Once their dependencies are loaded, they run their code, using headjs' callback.

Currently, as soon as my direct dependencies are loaded, my complete callback runs. The problem is that I need my complete callback to wait for the dependencies of my dependencies to load, and for my dependencies to run their complete callbacks. In other words, my complete callback should run last.

In headjs, my app code currently runs as soon as its direct dependencies are fulfilled; but it should wait until its indirect dependencies are fulfilled, too. The only solution right now is to add my dependencies' dependencies to my list of dependencies - but I shouldn't have to know anything about my dependencies' dependencies.

@TriMoon
Copy link

TriMoon commented Apr 15, 2013

You mean you want something like

head.done('dependency', function() {
....
});

Which should be called when all dependencies of 'dependency' are done loading?
I think that's a nice idea...

@jpmckinney
Copy link
Author

I think this should be the default behavior. I can't think of any example where "dependency" can be considered done loading while none of its dependencies are done loading. If such an example exists, I would say that those dependencies aren't really dependencies!

@TriMoon
Copy link

TriMoon commented Apr 15, 2013

Well head.js doesn't use the notion of dependency actually like you interpret it.
It just has a "ready", hence the name, to give the possibility of parallel loading after some other script has been loaded.
Those scripts that are loaded using head.ready() are not scripts that are technically checked to see if they actually require the previous step.
Thats why it has no conditions to check for valid loading.

I know what you want, but that functionality is more something of require.js, not that of head.js IMHO 😄

@jpmckinney
Copy link
Author

Actually, require.js doesn't do it either. Only LAB.js does this properly. requirejs/requirejs#710

@TriMoon
Copy link

TriMoon commented Apr 15, 2013

Oh ok, i just assumed so because of its name, i don't use either 😄
But...now that i think about it, you could actually code functionality like that in your own loading logic.
Just make good use of head.feature() and delay/repeat your loop while the conditions are not met yet 😄

Just keep in mind that head.ready() is not the same as a "Include <xxx.h>", "require <xxx.cpp>" or similar directive in other languages that get compiled...

@jpmckinney
Copy link
Author

Btw, I'm using head.js not head.ready (maybe they're functionally similar though in terms of this discussion).

It seems very weird to me. In every other language (take Ruby for example), if you require a file foo.rb, and that file requires more files bar.rb and baz.rb, then the loading order is bar.rb, baz.rb, foo.rb and then your script that started the chain. In head.js, the order is foo.rb, your script, bar.rb and baz.rb - which is weird.

I expect script loaders that have any concept of "run this before that" (which head.js does) would respect this simple order that exists elsewhere.

I guess I can hack something together with head.feature but it'd be a very strange way of doing things (using the presence of CSS classes to determine whether a JS file's dependencies have been met...).

@TriMoon
Copy link

TriMoon commented Apr 15, 2013

Well thats because those language provide those mechanisms as part of their structured language, while Javascript does not....
The issue you have is actually with Javascript in general not with the functionality of a utility like headjs.

When you make use of head.feature() like i mentioned, i suggest you use something similar to the code below to re-call a loop if your conditions are not met 😄

head.ready('someid', function(){
    head.feature('a_loaded', true);
});

head.ready('someid', function(){
    head.feature('b_loaded', true);
});

(function(){// To prevent global name polution.
    (function areWeDone(){
        if(head.a_loaded && head.b_loaded){
            do your stuff
            or load more with head.js()
        }else{
            window.setTimeout(areWeDone,50);// This delays and re-calls our loop.
        }
    })();// define+execute
})();

You could ofcourse also use your own global-object with properties instead of head.feature() for this functionality...

@TriMoon
Copy link

TriMoon commented Apr 15, 2013

Ohh ps.
head.js() Loads a script unconditionally, while optionally creating a tag for it.
head.ready() Only starts some code if the script with a tag has been loaded...
They are not the same 😄

@jpmckinney
Copy link
Author

Is there any way to have multiple files in head.ready, like in head.js?

I think CommonJS' require method acts like similar methods in other languages - since we don't have CommonJS in the browser, I'm looking for possible shims, and script loaders looked promising.

Thanks for the code - if any of the files fail to load (e.g. 404) the timeout will repeat forever though.

@TriMoon
Copy link

TriMoon commented Apr 15, 2013

You better refer to the documentation at: http://headjs.com/#api

About the infinite looping on not-found (404), that will ofcourse happen with the above code 😄
You could defend against that with your own logic to test the total waited time 👅

@jpmckinney
Copy link
Author

I've read the docs. I guess it's impossible to declare multiple files within a head.ready. Workaround seems to be to nest the head.ready calls. On the bright side, the dependencies seem to be resolving properly!

For posterity, code looks like:

head.js('a.js', 'b.js', 'c.js');

head('b.js', function () {
  head('c.js', function () {
    // Code 1
  });
});

And in b.js you can have:

head('a.js', function () {
  // Code 2
});

And the order of execution will be correct! a.js will run before "Code 2" in b.js, and b.js and c.js run before "Code 1". I've updated the jsFiddle to demonstrate: http://jsfiddle.net/TWDy4/3/

Thanks for your patience!

@TriMoon
Copy link

TriMoon commented Apr 15, 2013

np yw 😺
And thanks for that fiddle link, it might come in handy someday, i keep forgetting to bookmark it 😀

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

No branches or pull requests

2 participants