DEV Community

Cover image for How to Make your Console Output Fun and Interactive in JavaScript and Node.js
Coderslang: Become a Software Engineer
Coderslang: Become a Software Engineer

Posted on • Originally published at freecodecamp.org

How to Make your Console Output Fun and Interactive in JavaScript and Node.js

In this tutorial, you'll learn how to add a randomized delay to the console.log statements in JavaScript and Node.js.

intro-gif

Why would you want to do this?

First of all, programming should be fun. And making a boring thing like console.log look nice is very pleasing.

If you want to get quick access to the source code, you can check out this GitHub repository.

Step 1: Create a function that takes the string and passes it into console.log

To make sure that every step is clear, we'll start small and create a function that accepts a string as a parameter and logs it to the console.

const log = (s) => {
  console.log(s);
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Log characters of the string one-by-one

Before we can add a delay between the output of the individual chars, we need to make sure that they're actually split.

Let's add a for loop that iterates over each letter of the string and prints it to the console.

const log = (s) => {
  for (const c of s) {
    console.log(c);
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: How to fix the newline issue

Now, each letter is printed on a new line as every call to console.log adds an empty line.

We'll replace the console.log with process.stdout.write which essentially does the same thing, but doesn't add a new line after the output.

Now, however, we've lost the newline in the very end of the output, which is still desirable. We'll add it by explicitly printing the \n character.

const log = (s) => {
  for (const c of s) {
    process.stdout.write(c);
  }
  process.stdout.write('\n');
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Implement the sleep function

In JavaScript, we can't simply stop the execution of the synchronous code for some amount of time. To make this happen, we need to write our own function. Let's call it sleep.

It should accept a single parameter ms and return a Promise that resolves after the delay of ms milliseconds.

const sleep = (ms) => {
  return new Promise(resolve => setTimeout(resolve, ms));
};
Enter fullscreen mode Exit fullscreen mode

Step 5: Add the delay

So, we're ready to add a delay to our output! We need a couple of things here:

  • add a parameter delay to the function log
  • make the function log asynchronous by adding the keyword async
  • call a sleep function that will delay the next loop iteration by delay milliseconds
const sleep = (ms) => {
  return new Promise(resolve => setTimeout(resolve, ms));
};

const log = async (s, delay) => {
  for (const c of s) {
    process.stdout.write(c);
    await sleep(delay);
  }
  process.stdout.write('\n');
}
Enter fullscreen mode Exit fullscreen mode

Step 6: Implement randomized delay

The output will look even better if we randomize the timing.

Let's add another boolean parameter randomized to the function log. If it's true, then the argument passed into sleep should be in the range from 0 to delay milliseconds.

const sleep = (ms) => {
  return new Promise(resolve => setTimeout(resolve, ms));
};

const log = async (s, delay, randomized) => {
  for (const c of s) {
    process.stdout.write(c);
    await sleep((randomized ? Math.random() : 1) * delay);
  }
  process.stdout.write('\n');
}
Enter fullscreen mode Exit fullscreen mode

I've used a ternary operator, but you can replace it with a regular if statement:

if (randomized) {
  sleep(Math.random * delay);
} else {
  sleep(delay);
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Make the log configurable

Right now, we've implemented pretty much everything we wanted to. But calling it isn't very clean as we have to pass the delay and randomization flag every time we want to print something to the console.

log('Hello, world!', 100, true);
log('What\'s up?', 100, true);
log('How are you?', 100, true);
Enter fullscreen mode Exit fullscreen mode

It'd be nice if we could have a configurable log that could be called with a single parameter - a string that we want to output.

To do this, we'll have to rewrite our code. Here's the plan:

  • wrap all current functionality into a single function funkylog that accepts an object with 2 fields, delay and randomized
  • funkylog should return the anonymous arrow function. Its implementation should be the same as log, that we've implemented on steps 1 through 6
  • parameters delay and randomized should be removed from the log function as now they'll be passed down from the funkylog
const funkylog = ({ delay, randomized }) => {
  const sleep = (ms) => {
    return new Promise(resolve => setTimeout(resolve, ms));
  };

  return async (s) => {
    for (const c of s) {
      process.stdout.write(c);
      await sleep((randomized ? Math.random() : 1) * delay);
    }
    process.stdout.write('\n');
  }
};
Enter fullscreen mode Exit fullscreen mode

Step 8: Add the finishing touch

Let's take a look at what we've got:

const log = funkylog({ delay: 100, randomized: true });

log('Hello, world!');
log('What\'s up?');
log('How are you?');
Enter fullscreen mode Exit fullscreen mode
  • We can create a configurable logger using the function funkylog
  • We can select any delay we want
  • Using the logger doesn't require us to pass the delay every time we call it

One more improvement that we can make is providing a default value for the delay parameter.

const funkylog = ({ delay = 100, randomized }) => {
    ..
    ..
Enter fullscreen mode Exit fullscreen mode

So, now we can create the funkylog without any arguments and it will still work!

const log = funkylog();

console.log('Hello, world!');
Enter fullscreen mode Exit fullscreen mode

Improvement ideas

As I've said from the very beginning, first of all, programming should be fun. Otherwise, it'll become a routine and you won't enjoy doing it.

Do make further improvements to the funkylog and let me know what your results look like! For example, you can spice up the output by colorizing it. You can use the npm module chalk for it.

Then, once you have implemented different colors, you can add another flag that would add an additional delay between the words in the string.

Thank you for staying with me, throughout the whole tutorial!
I write a programming blog at learn.coderslang.com and build a Full Stack JS course.

Top comments (2)

Collapse
 
sebring profile image
J. G. Sebring

I've been at a seminar where the "slides" where all pages with pretty logs in console. Some of the audience didn't even realized it was the console log until it came up during the last minute of questions.

Very snazzy indeed. I'd prefer it over PPT any day =)

Collapse
 
andrewbaisden profile image
Andrew Baisden

Cool idea i like it.