In this post, we’ll be looking at a few examples showing asynchronous and synchronous JavaScript. It’s a language of multiple flavors.

  • Procedural & Functional
  • Object-Oriented
  • Asynchronous & Synchronous
  • Structured
  • Prototype-based
  • Event-Driven
  • Concurrent

What is Synchronous Programming?

In synchronous execution, you have to wait for the current task to finish before the next one starts. That being said, If we are talking in terms of threads, each thread can be allocated to perform a particular task. This way multiple separate tasks can be processed separately & simultaneously. PHP does this in the default setting.

Speaking in JavaScript terms, It means the execution won’t move to the next line before the current line has completed all processing. Like a line after a for loop will only be executed when all of the loop’s iterations finish.

NodeJS is famously single-threaded.

What is Asynchronous Programming?

In Asynchronous programming, multiple tasks can be called at any time, without completion of previous ongoing tasks. The same logic applies even if we talk in thread terms, just different queues.

Speaking in JavaScript terms, when an asynchronous function is called, there is a callback function provided to it, this callback function is called (when work is done) with processed data (or an error). This callback can be provided by different means. In terms of streams, events are used, which also take in a callback function and the same process follows.

Not all callbacks represent an asynchronous function, like Array.prototype.map().

I, personally prefer Promises.

Synchronous vs Asynchronous Execution

This image explains the execution process in both scenarios. I found it on Github.

Synchronous vs Asynchronous Programming: Execution Process

Let’s Dive into Synchronous vs Asynchronous Examples in JavaScript

Nowadays async & await is preferable over a callback hell. I mean can you imagine using .then() chained 10-15 times when using something like Puppeteer? The trick is to put all of these in a single try-catch block.

You will notice that console.log() is synchronous.

1. [Synchronous & Asynchronous] Reading files using the fs module on Node

This the API that came to my mind first, because it provides both, sync and async versions of most of its functions.

const fs = require("fs");

/**
 * Synchronous version
*/
try {
  const data = fs.readFileSync("./file.txt", "utf8");
  console.log(data); // using the data
} catch (error) {
  console.error(error); // catching error
}

/**
 * Asynchronous version
*/
fs.readFile("./file.txt", "utf8", (error, data) => {
  if (error) return console.error(error); // catching error
  console.log(data); // using the data
});

2. [Asynchronous] Using Fetch API in Browser

Fetch API provides a great way to make requests from a client to API.

fetch("https://jsonplaceholder.typicode.com/todos/9")
  .then(response => response.json()) // converts to JSON format, asynchronously
  .then(json => console.log(json)) // using the data
  .catch(error => console.error(error)); // catching error

3. [Synchronous] For & While Loop

Running a loop is the textbook example of synchronous execution. This code can run in Node or a browser.

// For loop
console.log("Foor loop starts");
for (let i = 0; i < 10; i++) {
  console.log(i, "For Loop");
}

// While loop
let i = 0;
console.log("While loop starts");
while (i < 10) {
  console.log(i, "While Loop");
  i++;
}

4. [Asynchronous] Connection to MongoDB and Selecting a Database in Node

MongoClient allows an easy way to connect to MongoDB and allows us to perform all operations. Most Database Operations you encounter will be Asynchronous.

// install mongodb driver by, npm install mongodb --save
const { MongoClient } = require("mongodb");

MongoClient.connect("mongodb://localhost:27017", (error, client) => {
  // this function is a callback
  if (error) return console.error(error); // catching error

  const db = client.db("testDB"); // using data

  client.close(); // using data
});

5. [Synchronous] DOM Manipulation in Browser

All DOM operations in Browsers are synchronous.

const element = document.getElementById("elementID"); // gets the element
element.classList.add("some class"); // adds a class to element
element.click(); // clicks on element
console.log(element); // logs the element to console

6. [Asynchronous] Creating a Promise Function and Using Async Await

In this example, I’ll be showing the creation of sample Promise function and executing it properly using async/await.

// This function returns a promise which resolves with random number
function getRandomNumber(min, max) {
  return new Promise(resolve => {
    // using timeout to make it wait it by 600ms
    setTimeout(() => {
      resolve(Math.ceil(Math.random() * (max - min) + min)); // Math functions are synchronous btw.
    }, 600);
  });
}

// self executing async arrow function.
(async () => {
  const first = await getRandomNumber(1, 10);
  const second = await getRandomNumber(10, 100);
  const third = await getRandomNumber(100, 1000);
  console.log(first, second, third);
  // we can enclose this in try/catch block, but there can't be any error in this example.
})();

7. [Synchronous] Random Number generator without Promise

This is the above example but in a synchronous way.

// This function returns random number
function getRandomNumber(min, max) {
  return Math.ceil(Math.random() * (max - min) + min);
}

// self executing async arrow function.
(() => {
  const first = getRandomNumber(1, 10);
  const second = getRandomNumber(10, 100);
  const third = getRandomNumber(100, 1000);
  console.log(first, second, third);
})();

8. [Asynchronous] Basic Puppeteer usage with Async/Await

In this example, we are using the Puppeteer package, which is an awesome tool for web automation.

const puppeteer = require("puppeteer");

(async () => {
  try {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto("https://example.com");
    await page.screenshot({ path: "example.png" });
    await browser.close();
  } catch (error) {
    console.log(error);
  }
})();

9. [Synchronous] Writing a text file via fs module

Pretty basic usage of Node’s fs module.

const fs = require("fs");
try {
  fs.writeFileSync("./info.txt", "Some random data"); // writes a file
} catch (error) {
  console.error(error); // catches error
}

10. [Asynchronous] Mongoose Model create

In this example, we’ll use mongoose models’ .create() function.

const mongoose = require("mongoose");
// connection must be established

// creating a model
const Sample = mongoose.model("Sample", new mongoose.Schema({ data: String }));

Sample.create({ data: "Some data to save" })
  .then(sample => console.log(sample))
  .catch(error => console.error(error));

11. [Synchronous] Creating an HTTP server in Node

We’ll be creating a simple HTTP server with Node’s http module.

const http = require("http");

http
  .createServer(function(req, res) {
    res.writeHead(200, { "Content-Type": "text/plain" });
    res.write("Hello World!");
    res.end();
  })
  .listen(8080);

12. [Asynchronous] Using fs.createReadStream to get data from a file

Now we’ll be using async/await to read chunks from a readable stream.

const fs = require("fs");

(async () => {
  const readStream = fs.createReadStream("./info.txt", { encoding: "utf8" });
  for await (const chunk of readStream) {
    console.log(chunk);
  }
})();