Let's say the progression of tasks is triggered with a window
load
like this,
window.addEventListener("load", doTheseFirst, { once: true });
function doTheseFirst()
{
// Show some pictures and play some sounds for 3 seconds
setTimeout(thenDoThese, 3000);
}
function thenDoThese()
{
// Show other pictures and play other sounds for 5 seconds
setTimeout(andThenDoTheseToo, 5000);
}
function andThenDoTheseToo()
{
// Maybe display some kind of option which will
// allow the user to choose how to proceed further
someButtonElement.addEventListener("click", whenButtonIsClicked);
}
function whenButtonIsClicked()
{
// etc etc
// You get the idea
}
And let's say we have a fetch()
that fires practically at the same time with either window
load
or the addition of the event listener.
An example of which could look like this,
fetch("somefolder/notification.txt").then(function(response){return response.text();}).then(function(contentOfTheTxtFile){ /*What to do when the file is ready*/ });
// Assume that download speed is unpredictable
window.addEventListener("load",function(){ doTheseFirst(); }, { once: true });
// ...
// ...
In this case the time of completion for fetch()
is totally UNCERTAIN i.e. we do not know at what exact moment fetch()
will actually get the file. Therefore the situation resembles a moment like the one seen in the image,
And yet what if we must PAUSE the task chain as soon as fetch()
is done and ready with the file and then UNPAUSE it after some kind of dialog box or notification msg is displayed.
The easy solution for that is using an alert
box since it blocks/pauses the code execution automatically and respects the remaining milliseconds in whichever setTimeout
was ticking at that moment. The following code makes the alert
box pop up as soon as fetch()
gets the content from the txt
file. Recall that fetch()
and window
load
are working independently.
fetch("somefolder/notification.txt").then(function(response){return response.text();}).then(function(contentOfTheTxtFile){ alert(contentOfTheTxtFile); });
This works because when the alert
box is closed, the main code goes back to its normal flow with a perfect UNPAUSING effect, just as needed.
How do we do the same thing without using a crude
alert
box that we cannot assign any styles to? Can we make it so that the code execution is paused as soon asfetch()
gets the file and then it is unpaused immediately once the user clicks something like an OK or NEXT button?
In other words, is it possible to mimic the behavior of alert()
?
NOTICE: This particular research has been initiated during the development of SPEAKWORLDLANGUAGES app
fetch
is asynchronous, which basically means
fetch('some_folder/some_file.xyz').then();
// Here at this point fetch has just started looking for the file and will be busy trying to get it
// And yet
console.log("This will immediately show regardless of how long it takes for fetch to complete");
There are two ways to make it act as if it was synchronous which means delaying all following tasks until fetch is complete. The first one is,
.then()
notation call the next task handler function in the function chain via .finally()
Like
fetch('some_folder/some_file.txt').then(response => {return response.text();})
.then(text => { /*Do what you want with the contents of the txt file*/ })
.catch(error => { console.error('fetch could not get the file', error); })
.finally(whenFetchIsDone);
function whenFetchIsDone() {
console.log("This will show only after fetch completes either with or without success");
// Here we can call a function like goAheadAndPerformTheNextTaskInLine();
}
The other way is
await
inside an async
function with a try
catch
finally
blockLike
async function fetchData() {
try {
const response = await fetch('some_folder/some_file.txt');
if (!response.ok) { throw new Error('fetch has failed'); }
const theText = await response.text();
// Do what you want with theText
} catch (error) {
console.error('could not read file', error);
} finally {
console.log("This will show only after fetch completes either with or without success");
// Here we can call a function like goAheadAndPerformTheNextTaskInLine();
}
}
fetchData();
Note that by using either method it is possible to chain multiple fetch tasks so that files will be downloaded one by one if necessary.