How can you wait until GWT is ready externally? (after onEnterModule)

845 views
Skip to first unread message

dougx

unread,
Aug 6, 2009, 2:09:52 AM8/6/09
to Google Web Toolkit
How can you wait until after onModuleLoad() has been invoked for an
application in external javascript?

Should be quite a simple matter:
- I have a GWT aplication that publishes a static JS API via JSNI.
- I have a page that uses that API.

I should be able to do this:
<body onload="apiTest();">
<script src="js/NetLoaderAPI/NetLoaderAPI.nocache.js"></script>
<script>
function apiTest() {
NetLoaderAPI.startUnitTests();
}
</script>
</body>

However, I can't use it, beacause I get an error like this:
"TypeError: window.NetWorkerAPI is undefined"

What? How is there some kind of delay between scripts loaded and run,
and the document ready event?

I have, for reference, compiled in xs mode, so the gwt code is not
being loaded in an external iframe.

ie. The API js is being included directly into the page header,
firebug shows it as:
<script src="http://localhost:8080/js/NetLoaderAPI/
9B08C2C4C155D60688C70B5ED70CC3CA.cache.js">...</script>

~
Doug.

olivier nouguier

unread,
Aug 6, 2009, 3:06:36 AM8/6/09
to Google-We...@googlegroups.com
hi,
 On "simple"  solution:

* In your html/js code define a:

function toBeCalledByGWT{
 NetLoaderAPI.startUnitTests();
}

* Call this function by JNSI at the end of onModuleLoad().


public void onModuleLoad(){
/*
... Standard GWT code.
*/

callJSInPage();

}

public void native callJSInPage() /*-{
  $wnd.toBeCalledByGWT()();
}-*/;


HIH
--
A coward is incapable of exhibiting love; it is the prerogative of the brave.
--
Mohandas Gandhi

dougx

unread,
Aug 6, 2009, 4:11:03 AM8/6/09
to Google Web Toolkit
Yes, that does work. However, it's awkward.

For example, if someone using jquery were to use my API, it would be
nice for them to be able to do this:
$(function() {
MyAPI.XXX(...);
});

Not this:
myApiReady() {
MyAPI.XXX(...);
}

Big deal right? ...but imagine how it scales. Say you depend on three
GWT API's. Now you're looking at something like this:

var readyStates = {'one' : false, 'two' : false, 'three' : false };
myReallyActuallyReallyReadyFunction() {
...
}
function myApiOneReady() {
readyStates.one = true;
if (readyStates.one && readyStates.two && readyStates.three)
myReallyActuallyReallyReadyFunction();
};
function myApiTwoReady() {
readyStates.two = true;
if (readyStates.one && readyStates.two && readyStates.three)
myReallyActuallyReallyReadyFunction();
};
function myApiThreeReady() {
readyStates.three = true;
if (readyStates.one && readyStates.two && readyStates.three)
myReallyActuallyReallyReadyFunction();
};

Ouch.

I still don't understand why the onModuleLoad kicks off after the
onLoad event; unless GWT is specifically waiting for the onLoad event
before it kicks off its own internal processes.

I suppose that vaguely makes sense, but it means that as an API
platform it's vastly unuseful, unless there's a way to turn it off.


~
Doug.


On Aug 6, 3:06 pm, olivier nouguier <olivier.nougu...@gmail.com>
wrote:

pmonestie

unread,
Aug 7, 2009, 11:04:23 AM8/7/09
to Google Web Toolkit
You can tweak the linker stuff in Gwt, however it gets a little
complicated.
I tried to write a linker that would load Gwt 'right away' but I had
issue with IE so I gave up on this.
I did write a modified linker though that provides a callback
mechanism:
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/3c613fd1ee857b09/d94db4f30c63f910#d94db4f30c63f910

All in all the way gwt loads though understandable, is not very
convenient when you you it in conjunction with Js.
Pierre

David

unread,
Aug 8, 2009, 3:02:49 PM8/8/09
to Google-We...@googlegroups.com
I'm not 100% following your question, so excuse me if my answer does
not match your question.

Why would you need to have a toBeCalledByGWT for every method you want
to expose from GWT ?

I presume you have created an API in GWT and want to expose it outside of GWT ?
Just make sure that the onModuleLoad exposes all the methods (one way
or another) and at the end you just call one method on the window
object to indicate that the API is ready to be used. So you JS code
just needs to wait until that method is invoked before starting

If you want to use multiple GWT APIs this way, I guess the best thing
to do is to have one onModuleLoad that invokes the injection of all
the APIs in JS and then call one callback to kickstart your
application. The idea of GWT is that you compile everything in one
application to improve optimisations and to have a small as possible
JS.

Why is the GWT API not fully initialized ? Well because it is
actually loaded by a hidden IFrame. Additionally with GWT 2.0 we will
be able to actually load parts on demand through runAsync support.

David

dougx

unread,
Aug 9, 2009, 9:13:58 PM8/9/09
to Google Web Toolkit
Quick answer is: If you're providing a series of APIs to a third
party, you:
1) Don't want to give them the source code to recompile them
(potentially).
2) Don't want to make their life difficult by forcing them to
recompile.
3) Don't want to step outside of what is 'normal' for a JS library (no
extra custom ready functions...)

I understand what you're saying; yes, linking it all together is more
efficient. Yes, you can bind everything together that way and you
don't need multiple ready functions. Its a great way of building a
rich net app.

However, for JS mashups, you don't want a single page application that
does everything. You want something that compiles into a generic
robust usable JS API, that is easy to use and obviously interact with
other JS APIs.

Incidentally, as I mentioned, the javascript isn't being loaded in an
iframe. I'm compiling in xs (cross site scripting) mode, which means
the JS is added as an inline element in the head. The google code
launcher specifically waits until after everything else before it
launches itself (I presume to ensure the DOM is ready before kicking
off the application init), but I would have been pleased if maybe the
module constructor was run on load, and only onModuleLoad waited until
after body.onload was called. Oh well.

I've come to realize that GWT is ill suited to what I'm doing. I'm
quite disappointed really.

~
Doug.

On Aug 9, 3:02 am, David <david.no...@gmail.com> wrote:
> I'm not 100% following your question, so excuse me if my answer does
> not match your question.
>
> Why would you need to have a toBeCalledByGWT for every method you want
> to expose from GWT ?
>
> I presume you have created an API in GWT and want to expose it outside of GWT ?
> Just make sure that the onModuleLoad exposes all the methods (one way
> or another) and at the end you just call one method on the window
> object to indicate that the API is ready to be used. So you JS code
> just needs to wait until that method is invoked before starting
>
> If you want to use multiple GWT APIs this way, I guess the best thing
> to do is to have one onModuleLoad that invokes the injection of all
> the APIs in JS and then call one callback to kickstart your
> application. The idea of GWT is that you compile everything in one
> application to improve optimisations and to have a small as possible
> JS.
>
> Why  is the GWT API not fully initialized ? Well because it is
> actually loaded by a hidden IFrame. Additionally with GWT 2.0 we will
> be able to actually load parts on demand through runAsync support.
>
> David
>

David

unread,
Aug 10, 2009, 5:43:57 AM8/10/09
to Google-We...@googlegroups.com
Doug,

I see your point. Maybe you should address this question with the GWT
contributors ? I think you make a valid question. In theory it should
be possible with a custom linker, but it would be nice that this
linker was there already.

You might indeed have to question if GWT is the best choice if you
actually want your API to be exposed as pure JavaScript (as the
preferred or even only way of using it).

Having a callback does not sound as a big drawback to me. Sometimes
you have to trade off your API to the ease of developments as well.
The main advantage of downloading and intialising asynchronously is
that you give CPU back to the browser to render the UI. so the intial
wait time is lower.

David
Reply all
Reply to author
Forward
0 new messages