-1

So, I am making a fake operating system game inside the console in JS. And to load the OS I have a twirly loading function which I'll show now.

function OSLoad(OS = "", loadingTimeSeconds = 10) {
  var twirlTimer = (function () {
    var P = ["\\", "|", "/", "-"];
    var x = 0;
    return setInterval(function () {
      process.stdout.write(
        "\r" + P[x++] + " Loading " + OS
      );
      x &= 3;
    }, 250);
  })();

  setTimeout(() => clearInterval(twirlTimer), loadingTimeSeconds + "000");
}

I'm kind of a beginner, and I've ran into a problem with this function. I'm currently in the testing phase, so after this function is done I log to the console "OS Started!", but instead it logs the loading and "OS Started!" at the same time. I assumed that setTimeout would make it pause until it's done, which it didn't. What can I do to solve this?

The first thing that came to mind when I tried to solve this was using async, but as I said, I'm a beginner, and I never actually learned how to use async... So if you could teach me how to use that or an even better solution please do.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • It's not really clear what you're asking. This code is asynchronous. Do you want to make it synchronous? `setTimeout` and `setInterval` are two functions for asynchronous code flow. – jabaa May 29 '23 at 18:06
  • 1
    To convert a seconds value to a milliseconds value, you multiply it by 1000. Adding zeros will work, but it is, well, weird. – Pointy May 29 '23 at 18:17
  • "*I never actually learned how to use async*" - yes, now is the time to learn about asynchronous event, callbacks, promises and `async`/`await`. – Bergi May 29 '23 at 18:24
  • PSA: It's 2023 and time to fully embrace `let` and `const` and let `var` retire. – tadman May 29 '23 at 18:34
  • Do you mean "asynchronous" as in `async function`? If so, you'll need to leverage `new Promise()`. – tadman May 29 '23 at 18:35

1 Answers1

1

The best way in JS to make code in JS look sync is using async / await.

Instead of using multiple setTimeout , intervals etc, your can create a simple Promise sleep function and then use this with await.

Below is a simple example. Most the code is to emulate the console.

//very simple console emulator
const pre = document.querySelector('pre');
const consoleBuffer = new Array(10).fill(' ');
let cpos = 0;
const consoleWrite = txt => {
  const s = txt.split('');
  for (const c of s) {
    if (c === '\r') cpos = 0;
    else consoleBuffer[cpos++] = c;
  }
  pre.innerText = consoleBuffer.join('');
}
window.process = { stdout: { write: consoleWrite } };


//OS Loader
const sleep = ms => new Promise(r => { setTimeout(r, ms);});

async function OSLoad(OS = "", loadingTimeSeconds = 10) {
  var P = ["\\", "|", "/", "-"];
  var x = 0;
  for (let lp = 0; lp < loadingTimeSeconds * 4; lp ++) {
    process.stdout.write(
      "\r" + P[x++] + " Loading " + OS
    );
    x &= 3;
    await sleep(250);
  }
  process.stdout.write("\r" + OS + " is loaded..");
}


OSLoad('Fake OS 4.01');
pre {
  height: 90vh;
  background-color: black;
  color: white;
}
<pre>
</pre>
Keith
  • 22,005
  • 2
  • 27
  • 44