Ways to retrieve text files prior to the webpage loading (synchronously)

I have a simple task at hand that I really want to accomplish - loading some glsl fragment shaders from the disk or server, and then initializing a WebGL web page. Web programming is not my forte; I usually prefer working on shaders and OpenGL in C++. If it weren't for WebGL, I wouldn't even bother with JavaScript. Little did I know how challenging it would be just to load a file in JavaScript. Then someone on Stack Overflow recommended using the fetch API, which seemed quite convenient. So, I gave it a shot:

// somewhere in HTML body 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 issue here is that fetch is asynchronous, so init_GLSLScreen(str_Primitives, str_RayTracer) executes before the shaders are loaded, resulting in an exception like "cannot compile shaders and stuff...". I don't want to deal with this asynchronous complexity; I want to go back to simple synchronous programming as quickly as possible. Debugging asynchronous code is a nightmare, and the program has nothing else to do until the shaders are loaded.

It seems there's no straightforward way to synchronize asynchronous and synchronous calls in JavaScript. There's no wait_to_resolve concept; we only have await, which doesn't actually make you wait but instead pushes the problem onto wrapper functions that need to be marked async.

To work around this, I can do the following:

<script>
var str_RayTracer  = "//RayTracer";
var str_Primitives = "//Primitives";
function initThis(txt){
   // 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; // I must return something for some reason
}

loadPage().then( txt => initThis(txt) );
//loadPage().then( initThis() ); // this doesn't seem to work
</script>

But I find this solution cumbersome because initialization is inherently a sequential operation. I believe I should be able to write normal sequential code without having to chain callback dependencies like this.

I've read through numerous threads on Stack Overflow addressing this issue, but there doesn't seem to be a satisfactory answer. It's mostly responses like "Oh, we don't do that here" accompanied by memes. The question of how to handle returning the response from an asynchronous call remains unanswered.

Everywhere I look, I see statements like "There's no way to do it without blocking the GUI." Okay, fine. But can someone please tell me how to do it while blocking the GUI? After all, the GUI can't even initialize until those files are downloaded.

I understand the benefits of non-blocking and asynchronous operations, especially when aiming for a responsive web page. However, there are times when waiting for a task to complete is necessary, and that choice should be left up to the programmer.

Answer №1

Can you explain how to achieve this without blocking the GUI?

You can use XMLHttpRequest with synchronous mode instead of fetch.

However, it is not recommended as it is considered deprecated. It's better to embrace asynchronous programming for web development. The following code demonstrates a sequential approach without using global variables:

<script>
async function loadTextfile(path) {
    var response = await fetch(path);
    return response.text();
}
async function loadPage() {
    var str_Primitives = await loadTextfile('Primitives.glslf');
    var str_RayTracer  = await loadTextfile('RayTracer.glslf');

    init_GLSLScreen(str_Primitives, str_RayTracer);
}

loadPage().catch(err => { console.error(err); });
</script>

You can further improve performance by loading both files concurrently. Simply modify the code like so:

async function loadPage() {
    var [str_Primitives, str_RayTracer] = await Promise.all([
        loadTextfile('Primitives.glslf'),
        loadTextfile('RayTracer.glslf'),
    ]);
    init_GLSLScreen(str_Primitives, str_RayTracer);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Struggling to remove the image tag from the jQuery ajax response

My web app is designed to send an ajax post request to a PHP script, which then returns a chunk of HTML data. This HTML includes an image and a table of information. The challenge I'm facing is how to extract the image from the rest of the HTML so tha ...

Struggling to get the findAndModify or Update functions to work properly in MongoDB. Despite fetching the desired data from my ajax call, I am unable to make any changes in the database

Here is the ajax code snippet: $(function () { $("#upvoteClick").click(function () { $.ajax({ type:"POST", data: {upvote: 2}, dataType: 'json', url:"http://localhost:9000/api/upvote" }).success(functi ...

Within the ASP.NET Framework 4, it is necessary to enable the Listbox control to trigger an event when a user double

Currently, I am developing a project in ASP.NET 4. I have encountered a situation where the regular ListBox in version 4.5 includes an attribute named OnMouseDoubleClick. However, since I am using ASP.Net 4, I am looking for the best approach to replicat ...

What is the method to display a group label using ng-table?

Does anyone have experience creating a group in ng-table? <div> <div ng-controller="ContractsController" style="position: relative;background:whitesmoke; border:1px solid lightgray; border-radius:5px; margin-top:0px; margin-bottom:5px; h ...

What is the method for transferring the value of a jQuery variable to a PHP variable without using AJAX?

Here is my JavaScript code: $('#affiliates_name').change(function(){ var id = $('#affiliates_name').val(); }); Below is the corresponding HTML: <select id="affiliates_name" style="display: none;" name="affiliates_name"> < ...

Incorporate a corner box feature to bring attention to the typed.js functionality

I have successfully integrated typed.js into my project and now I am looking to replicate the highlighted text with an excel-like box in one corner. I've managed to get the text typing out while also adding an SVG for the box in HTML, but I'm hav ...

"Launch HTML in a new tab when a button is clicked with the help of AngularJS

In my AngularJS page, I have an edit button that when clicked, needs to open the edit page in another tab. Is it possible to achieve this using Angular? I want to maintain access to the same controller and data - how can I make this work? Does anyone hav ...

Encountered an unexpected identifier error while executing a Nuxt.js project

I am utilizing the following technologies: Node.js version 6.14.2 NPM version 6.0.1 Ubuntu 16.04 Whenever I attempt to execute a project, I encounter the following error message: npm run dev node_modules/nuxt/lib/core/module.js:14 async ready( ...

What is the best way to extract information from a dynamically generated bootstrap form with changing fields and names?

In my MERN app, I have implemented a Bootstrap form where users can input various martial arts styles such as judo and bjj. React-tag-component is used to manage these styles. As users enter their preferred style, it gets added to an array named selected. ...

Is it possible to execute the .push() method on an array a specific number of times without using a for loop?

Currently, I am tackling the "Move Zeroes" Leetcode challenge. The task requires moving all zeroes to the end of the array without altering the sequence of non-zero elements. My strategy involves iterating through the array, splicing out each zero encounte ...

When trying to upload a file using multer, an error occurred stating "Unexpected field

My current issue involves using multer to upload an image from a form. However, I am encountering an Unexpected field error after uploading the image. In my HTML code, I have specified the file and file-model names as myFile. app.js var express = re ...

Modify the class of the focused element exclusively in Angular 2

I'm working on a project that involves several buttons and div elements. Currently, the divs are hidden, but I want to be able to reveal a specific div when its corresponding button is clicked. For example: If you click the first button, only the fir ...

Perform a bash command using PHP when an HTML button is clicked

Today, my brain seems to be on vacation. Currently, I have set up a Raspberry Pi with vlc running and connected to a mounted screen on the wall. There is a web page with simple controls to manage the pi, switch between different vlc streams, or stop stream ...

The extent of a nameless function when used as a parameter

I am currently developing a straightforward application. Whenever a user hovers over an item in the list (li), the text color changes to green, and reverts back to black when the mouse moves away. Is it possible to replace lis[i] with this keyword in the ...

Having trouble importing the hash-set module in TypeScript/SystemJS?

In the midst of developing an Aurelia project with TypeScript to generate JavaScript, I decided to incorporate another custom library called 'hash-set' (installed using jspm install npm:hash-set --save). However, I encountered difficulties in act ...

What are effective solutions to reduce the increasing Next.js bundle size caused by dynamic component lookup?

tldr: For more information, please visit the repository. The common.js file includes all dependencies, even though only one is used on the current page. http://localhost:3000/components/ComponentOne http://localhost:3000/components/ComponentTwo Live dem ...

Leverage Next.js to optimize data retrieval and facilitate seamless data sharing across different pages

I am currently seeking better solutions for data fetching in a Next.js application. I am not just looking for one solution, but rather multiple options so we can assess the pros and cons. The issue at hand At present, I have several pages that each conta ...

What is the best way to send user input text to a Vue method using v-on:change?

I am trying to pass the input value from my HTML to a Vue method called checkExist(). I need to get this value within the checkExist() method. Can anyone provide advice on how I can achieve this? I am new to Vue and could use some guidance. HTML: <inp ...

What is the best way to import modules in Typescript/Javascript synchronously during runtime?

I have a Typescript class where I am attempting to perform a synchronous import, however, the import is being executed asynchronously. My code snippet looks like this: --------------100 lines of code-------------------- import('../../../x/y/z') ...

Using JSON Values in JavaScript

Below is a JSON result structured like this : [{"Januari":"0","Februari":"0","Maret":"0","April":"0","Mei":"7","Juni":"0","Juli":"0","Agustus":"0","September":"0","Oktober":"0","November":"0","Desember":"0"}] What is the best method to input these values ...