I really want to do simple thing - load some glsl fragment shaders from disk/server, and than initialize WebGL web-page. I'm really not web programmer, normally I prefer programing shaders and opengl in C++. I would never put my hands on javascript if there would not be WebGL. I did not realized how hard it could be just to load a file in javascript. Then somebody on stack overflow recommend to use fetch API which seems quite convenient. So I tried like this:
// somewhere in HTML body far far away
<script>
var str_RayTracer = "//RayTracer";
var str_Primitives = "//Primitives";
fetch('RayTracer.glslf') .then(response => response.text()).then(text => str_RayTracer = text );
fetch('Primitives.glslf').then(response => response.text()).then(text => str_Primitives = text );
init_GLSLScreen(str_Primitives, str_RayTracer);
</script>
The problem is that fetch
is some asynchronous bullshit, therefore init_GLSLScreen(str_Primitives, str_RayTracer)
execute before the shaders are loaded => It throws an exception like cannot compile shaders and stuff ...
. I really don't want to stick into that asynchronous business, and I want to get out - back to decent synchonous programming - as fast as possible. because 1) debugging asynchronous stuff is hell, and 2) because the program have really nothing to do until the shaders are loaded.
It seems there is no simple way how to synchronize asynchronous and synchronous calls in javascript (which is strange - in every parallel programming language I know you have some synchronization points). There is nothing like wait_to_resolve
there is just await, which (despite to what the name suggests) does not really wait for anything. It just push the problem further by forcing you to make the wrapper function async
as well.
I can make it work this way:
<script>
var str_RayTracer = "//RayTracer";
var str_Primitives = "//Primitives";
function initThis(txt){
// for some reason I must take `txt` although I don't use it
init_GLSLScreen(str_Primitives, str_RayTracer);
}
async function loadPage(){
str_Primitives = await fetch('Primitives.glslf').then( r => r.text() );
str_RayTracer = await fetch('RayTracer.glslf' ).then( r => r.text() );
return 0; // for some reason I must return something
}
loadPage().then( txt => initThis(txt) );
//loadPage().then( initThis() ); // doesn't seem to work
</script>
But I don't like it, since initialization is inherently sequential operation. I don't see why I cannot write normal sequntial code, and instead should chain callback dependencies like this. That is like writing sequential program backwards.
I tried to read all threads about this issue on stack overflow ( e.g. 1 2 ), and there is no really useful answer. There is just "Oh, we don't do that here" meme. Best expressed here: How do I return the response from an asynchronous call?
Everywhere is written something like There is no way how to do it without blocking GUI
. OK, so what? Tell me how to do it with blocking the GUI
, please! Since the GUI cannot be even initialized until I download those files.
I understand that sometimes the non-blocking and asynchronous operations are useful, especially when you want to make responsive web-page. But sometimes not, sometimes you really want to wait until job is done, and the choice should be on programmer.