I am currently working on an Electron app to practice one's vocabulary. In essence, I have some sentences saved in one language, and if the user presses a button, a randomly selected sentence is translated into a different language, which the user then has to translate into another language.

Sometimes, the translation takes a couple of seconds, and during that time, I want to display a loading animation - I basically copied the code of #5 here (it's basically just the HTML element added in the function below plus come CSS).

function handleNextPhraseButtonClicked() {
    const loadElem = document.createElement("div");
    loadElem.className = "loading";
    loadElem.innerHTML = "Loading…"
    document.body.appendChild(loadElem);

    doTranslationStuffAndSetHTML();

    document.body.removeChild(loadElem);
}

Now, my problem is this: the loading animation is not displayed (even during long periods of waiting), and it seems as though that's because the code executes somewhat asynchronously. The animation per se works fine, as it is displayed if I don't remove it at the end of the function, but if I don't, then it never even appears, even if the translation stuff takes several seconds. The order of execution should be document.body.appendChild(loadElem); -> doTranslationStuffAndSetHTML(); -> document.body.removeChild(loadElem);, but it seems like it's document.body.appendChild(loadElem); -> document.body.removeChild(loadElem); -> doTranslationStuffAndSetHTML();, or something like that. I know that the translation is taking some seconds because the whole page freezes for that duration, until the translated sentence is displayed (all of which happens in doTranslationStuffAndSetHTML()). I have also tried using Promises, but to no avail. Can anybody help me out here? Is there maybe a way to check if the page has been updated, and a new element has been added to its HTML code (as in, not just added but is also displayed already)? Is it an issue of Electron, or is the compiler at fault here for trying to optimize code execution?

The actual code of doTranslationStuffAndSetHTML is the following:

function doTranslationStuffAndSetHTML () {
    currentID = vocabHandler.getRandomPhraseID();
    document.getElementById("phraseHeader").innerText = vocabHandler.getPhrase(currentID, languageToTranslateCode);
    vocabHandler.incrementShownCount(currentID);
    document.getElementsByClassName("answerInput")[0].disabled = false;
    if(document.getElementsByClassName("footer").length > 0) document.body.removeChild(document.getElementsByClassName("footer")[0]);
}

Though the only relevant point here is probably that vocabHandler.getPhrase calls a translation function, which calls a Python script which translates a given phrase into a specified language using the Google Translate API.

function translate(srcLanguageCode, destLanguageCode, text) {
    const { spawnSync } = require("child_process");
    const childPython = spawnSync("python", ["src/translate.py", srcLanguageCode, destLanguageCode, text]);
    var data = childPython.stdout.toString().substring(1,);
    return eval(convertString(data));
}
1

There are 1 answers

0
AudioBubble On

So, what fixed everything for me was literally just wrapping the function (including the removal of the loading animation!) into a setTimeout...

function handleNextPhraseButtonClicked() {
    const loadElem = document.createElement("div");
    loadElem.className = "loading";
    loadElem.innerHTML = "Loading…"
    document.body.appendChild(loadElem);

    setTimeout(() => {
        doTranslationStuffAndSetHTML();
        document.body.removeChild(loadElem);
    }, 0);
}

I have tried fiddling with promises more, but it really seemed as though await had no effect whatsoever on code execution, no matter what I tried.