Practical difference between async await and callback

In one of our tutorial, we learned how to create a function in async await and how to create a function that uses callback.

Video tutorial:

Asynchronous

Let’s say you want to send an email to a user. Following is a Node JS code that sends an email using a callback:

const transport = nodemailer.createTransport({
	host: "",
	port: 465,
	secure: true,
	auth: {
		user: "",
		pass: ""
	}
})

transport.sendMail({
	from: "support@adnan-tech.com",
	to: "",
	subject: "Test",
	text: "Hello",
	html: "Hello"
}, function (error, info) {
	console.log("Mail sent: " + (new Date()))
})

console.log("I am called: " + (new Date()))

In your terminal, you will see that the “I am called:” message will be displayed instantly. But the “Mail sent:” message will be shown after a few seconds, once the mail is sent. It means that all lines of your code are executed at once, irrespective of the fact that the sendMail function will take some. The code is executed without waiting for any function to complete. This is asynchronous programming.

Synchronous

This can be converted into a synchronous function. Following is the synchronous version of the above code:

// the function must be async if await is used inside it

app.get("/sendMail", async function (request, result) {

	// send an email using a callback
	const transport = nodemailer.createTransport({
		host: "",
		port: 465,
		secure: true,
		auth: {
			user: "",
			pass: ""
		}
	})

	const info = await transport.sendMail({
		from: "support@adnan-tech.com",
		to: "",
		subject: "Test",
		text: "Hello",
		html: "Hello"
	})

	console.log("Mail sent: " + (new Date()))

	console.log("I am called: " + (new Date()))

	result.send("")
})

If you run the code now, you will have to wait for the sendMail function to finish before you see your log messages. This is synchronous programming.

Now you have understood the difference, let’s discuss where you should use async await and where you should use a callback.

When to use async await

You should use the async await pattern when the next line of your code is dependent on the previous lines. For example, “you have to insert the record in the database only if the mail is sent successfully”. In this case, you must use async await so that your code will wait for the mail to be sent successfully, then it will insert it in the database.

When to use callback

A callback will be helpful when your code sections are independent of each other. For example, “send an email to the user and insert the record in the database.” In this case, your insertion query should not have to wait for the mail to be sent. The mail should be handled in a callback.

A guide to MEVN

MEVN stands for Mongo DB, Express JS, Vue JS, and Node JS. It is a technology stack used by developers to create full-fledged web applications. Most of the applications created in the MEVN stack are single-page applications. But it is up to you if you want to single page or multi-page web application.

Table of content

  1. What is MEVN ?
  2. Why MEVN ?
    • Same language for frontend and backend
    • Easy deployment
    • Seamless user experience
    • APIs for mobile apps
    • Mongo DB is scaled horizontally
    • Short learning curve
    • Better support for sockets
  3. Future of MEVN
  4. Projects developed in MEVN
  5. Where to learn MEVN ?
    • Official documentation
    • YouTube
    • Blogs
  6. Issues you will face in the development

Let’s get started.

1. What is MEVN ?

MEVN is a technology stack used to develop full-fledged web applications. You can easily create scalable web applications either single-page or multi-page applications. It is a new yet quickly evolving technology stack that has been adopted by a lot of developers already. Learning this will not only make you a frontend developer but a backend developer as well. Thus increasing your demand and reputation in the community.

Hiring a developer in this stack is easy for companies as well. Hiring individual developers for the backend and frontend is costly, especially for startups. So they end up looking for someone who knows both the backend and frontend.

2. Why MEVN ?

If you learn this technology stack, your demand is automatically increased since companies would love to have a developer that can handle both frontend and backend tasks. Even if you didn’t get a job as a full-stack developer, you can still get a job as either a frontend or backend developer since you can work in both.

Same language for frontend and backend

In this stack, the primary language is Javascript. Node JS is a Javascript runtime environment, Vue JS is a Javascript frontend framework and Express JS is a framework of Node JS for creating APIs. Mongo DB syntax is also very similar to Javascript. So you do not need to learn Javascript for the frontend and PHP or Python for the backend. One language i.e. Javascript is used for both sides (frontend and backend).

Easy deployment

Vue JS builds are minified code of HTML, CSS, and Javascript. So they can easily be deployed on most servers. You do not need to worry if your hosting supports PHP, Java, Python, or any other language. If your hosting supports HTML (which almost every hosting does) then you are good to go.

Node JS can also be easily deployed on Virtual Private Servers (VPS) or dedicated servers. You can check our detailed guide on how to deploy Node JS on VPS or dedicated servers.

Mongo DB can also be deployed on VPS or dedicated servers. But it can also be deployed on Mongo DB’s official site. You can check our tutorial for Mongo DB deployment.

Seamless user experience

Most of the apps created in this stack are single-page applications. They provide a better user experience since there is no page reload on any link. Only the required section of the page changes dynamically. Some of the websites that are single-paged are Gmail, Facebook, and Twitter.

APIs for mobile apps

Most of the rendering is done on the client side. This means you have to create APIs for each request. This helps you in the future when you want to develop mobile apps for your website. Android and iOS apps can easily communicate with APIs developed in Node JS.

Mongo DB is scaled horizontally

Horizontal scaling is performed by adding more nodes to the servers. Horizontal scaling is best for a non-relational database like Mongo DB since all the data is stored in a single document.

Moreover, if you have to add one more attribute to a single entity, you can easily add it to that document only. Unless in MySQL, where either you have to create a column that will result in assigning the value to all rows. Or you have to create a separate table and join them in each query which will slow down your application.

In Mongo DB, all data required for an entity is stored in a single document. No relationships are made. So data can be saved on different servers without being dependent on each other.

Short learning curve

If you know Javascript, you already know Vue JS. Unlike in React where you have to use JSX syntax, in Vue JS you can use legacy HTML and CSS code and use Javascript with it. If you know the basics of Javascript, spend a few hours on Vue JS official documentation and you will become a Vue JS developer.

Better support for sockets

Sockets are used for real-time communication. Like on Facebook, you do not have to refresh the page to check new notifications. Whenever a new notification is received, it automatically displays an alert. If you develop your web application in the MEVN stack, you will be able to add real-time features like alerts, notifications, chat messages, real-time collaborations, etc.

3. Future of MEVN

MEVN proving itself a bright future. A lot of developers are moving to this stack. It is in the race with MEAN and MERN stacks. It has solved a lot of issues that developers faced in web development. For example, during infinite scroll, the web page hangs due to too much data. Vue JS solved this by using the useVirtualList component. Node JS has solved real-time communication problems via sockets. And Mongo DB has solved the scalability problems and also the problems that came with tightly-coupled databases.

4. Projects developed in MEVN

To show you how easy it is to develop websites in this technology stack, we developed some projects in it. We have developed a chat app, a customer support ticketing system, and more.

5. Where to learn MEVN

You can learn this technology stack from many sources.

Official documentation

To stay updated with the latest versions and features, check out the official documentation of Vue JS. Node JS can also be learned from their official documentation. Mongo DB also came with outstanding documentation.

YouTube

Check this playlist to find a lot of tutorials on the MEVN stack.

Blogs

We have created many text-based tutorials on this stack.

6. Issues you will face in the development

You need to spend a lot of time to make the application up and running. The first version of your product might take more time and effort because you need to set up the APIs and basic functionality. However, we have created a boilerplate for authentication that will save you 100% time on rewriting the authentication code.

Add or update URL query parameter in Javascript

Create the following function in Javascript to add or update URL query parameter.

function addOrUpdateURLParam (key, value) {
    const searchParams = new URLSearchParams(window.location.search)
    searchParams.set(key, value)
    const newRelativePathQuery = window.location.pathname + "?" + searchParams.toString()
    history.pushState(null, "", newRelativePathQuery)
}

Now, whenever you want to add or update the URL, simply call the function in the following way:

addOrUpdateURLParam("name", "adnan-tech.com")

The first parameter will be the key of the parameter, and the second will be the value.

window.location.search: will return all the query parameters starting from “?”.

URLSearchParams: This will create an instance of URLSearchParams that will be used to manipulate URL query parameters.

searchParams.set(key, value): This will set the key value provided in arguments, but will not display yet in the URL.

window.location.pathname: It returns the relative path starting from “/your_website”. It DOES NOT include the query parameters starting from “?”.

searchParams.toString(): Will convert all the key-value pairs to a string. If there will multiple parameters set, then they will be separated by the “&” sign.

history.pushState: Will actually display the query parameters in the URL.

The first parameter to the “history.pushState” function is the “state”. It can be a push, pop, or null. The second parameter is not used anymore but not removed either, passing an empty string is safe. The third parameter is the new URL, here we are passing our new string variable to set the new URL with query parameters. More information can be found here.

Video tutorial:

Following this tutorial, I hope you will be able to add or update query parameter in your website’s URL using Javascript. If it helps, check out our tutorials on Javascript.

Ecommerce website in MEVN stack

It is a single-page ecommerce website developed in Vue JS. Vue JS is an open-source Javascript framework specifically built to design user interfaces and is widely used for creating single-page applications.

Node JS is a Javascript run-time environment developed for creating the backend of applications. Its framework Express is widely used for creating APIs. It is built to create scalable applications.

Mongo DB is a no-SQL database. It is a non-relational database system. It is easily scalable because the data is loosely coupled.

FeaturesFreePremium $100
Product management (admin panel)YesYes
Product listingYesYes
Product detailYesYes
Shopping cartYesYes
Checkout (PayPal & Stripe)YesYes
Order management (admin panel)YesYes
Order detailYesYes
Product specificationsYesYes
Stock managementYesYes
Search and sortYesYes
New order emailYesYes
Product reviewsNoYes
Shipping charges by countryNoYes
Product image compressionNoYes
Realtime chat between users and adminNoYes

Following is the feature list of this project:

  • Product management (admin panel)
  • Product listing
  • Product detail
  • Shopping cart
  • Checkout (PayPal & Stripe)
  • Order management (admin panel)
  • Order detail
  • Product specifications
  • Stock management
  • Product reviews
  • Search and sort
  • Shipping charges by country
  • Email to admin whenever a new order is placed
  • Product image compression
  • Realtime chat between users and admin

Add product

Admin will be able to add products. He will enter the name of the product. Add a little description of the product. And set the price of the product. The price will be in dollars. Along with them, the admin can upload one or more images of the product.

Product listing

Users will see the products added by the admin on their home page. The latest products are displayed first. Along with each product, a button will be displayed to view the detail of the product.

Product detail

Users can view the detail of the product. If the product contains more than one image, then it will be displayed as a beautiful slider. From this page, users will also be able to add products to the cart. If the product is already added to the cart, then he will be able to remove it from the cart.

Shopping cart

Users can add the product to the cart. From the cart’s page, he will be able to adjust the quantity of the product. There will be multiple products in the cart and you can set the quantity of each product separately. You will also see your total bill as soon as you change the quantity of any product added to the cart.

Checkout (Stripe & PayPal)

After adding the products to the cart and setting each product’s quantity, the user can go to the checkout page. Here, he can either pay via Stripe or PayPal. Both payment methods accept debit and master cards securely. When the user made the payment, his payment is verified from the server. If verified, then a new order will be created in the database.

Order management

Whenever a user made a payment via Stripe or PayPal, an order will be created. All orders will be displayed on the admin panel ordered by latest to oldest. By default, the status of the order is “Processing”. But admin can change the status of the order to “Completed” when the product is delivered to the customer.

Admin will also be able to view the total amount of the order, the payment method customer has used, and the user’s shipping details.

Order detail

Admin can view all the products that were included in each order. He can manually verify the payment by clicking the payment method. If he clicks “Stripe”, he will be redirected to the Stripe payments page. If he clicks “PayPal”, then he will be redirected to the PayPal business page. Admin can check the name, email, and phone of the user and also his shipping address.

Product specifications

Admin can add the specifications of each product and the user will be able to see it on the product detail page.

Stock management

Admin can set the number of units in stock for each product. When the user makes an order, then the number of units he has selected will be subtracted.

Product reviews

User can give reviews on a product and it will be displayed to all users who visit that product. Admin will have the ability to remove any review, for example, spamming, etc.

Search and sort

Users can search by product by its name, description, category, or specifications. Users can also sort the products by date or by price.

Shipping charges by country

Admin can set the shipping charges by each country because, in a global eCommerce website, users place orders from all over the world. For example, if your store is located in USA and someone places an order from the UK. Then you charge the shipping fee differently than other countries.

Email to admin whenever a new order is placed

Admin will receive an email whenever a new order has been placed by the user.

Product image compression

Now you can compress the product images from the admin panel. The 3 MB image can be reduced to just 182 KB and the image will still be of great quality.

Realtime chat between users and admin

Users will be able to have a chat with the admin to know more about a product before placing an order. I believe every eCommerce website should have this feature.

We are constantly updating this project and adding more features and enhancements to it. Following are all the builds that are released till today.

  • In the very first release, we build the basic E-commerce version where the admin can add products and users can see them. Add them to carts and order them. We also added Stripe and PayPal payment methods.
  • In the second release, we added more features. Allowing users to give reviews about a product. Allowing admin to charge a different shipping fee for each country and many more.
  • In the third release, we added functionality to compress product images and to have real-time chat between users and admin.

Free version

https://github.com/adnanafzal565/ecommerce-mevn-stack

Share local storage between websites – Javascript

In this article, we are going to teach you, how you can share local storage between websites using Javascript. Local storage is not accessible even within subdomains. So if I set the value in one subdomain, it will not be accessible in another subdomain.

Video tutorial:

To share the local storage value between websites, first, we need to create an iframe tag in the source website.

<iframe src="http://destination-website.com/saveLocalStorage.php" style="display: none;"></iframe>

The value of src attribute will be the path of the destination website. And we will hide the iframe using the CSS property display: none; so it will not be visible on the source website.

Then we will create a script tag and call a function that will be called when the page is loaded. You can also call it on any function you want, for example, when the user is logged in, you want to share the user’s authentication token to another website. In that case, you can write the below code inside your login function, but for the sake of simplicity, we are calling it inside the page load function.

<script>
    window.addEventListener("load", function () {
        // [code goes here]
    })
</script>

The following code will go inside the section. First, we will get the iframe DOM object.

const iframe = document.querySelector("iframe")

Then we will get the iframe content window.

const wind = iframe.contentWindow

Then we will set the data that needs to be sent.

const data = {
    name: "adnan-tech.com"
}

After that, we will call the postMessage function from the iframe content window object i.e. wind. The second parameter of the postMessage will be * in double quotes which means there is no preference for target origin.

wind.postMessage(JSON.stringify(data), "*")

You can learn more about it here.

Now we will come to the destination website, the file name will be saveLocalStorage.php. Create a script tag and attach a listener that will be called when the message is received. The second parameter will be a function and it will have an argument event (e).

<script>
    window.addEventListener("message", function (e) {
        // [destination code goes here]
    })
</script>

The following code goes in the [destination code goes here] section. First, we will check if the origin of the message is our source website because otherwise, any other website can also send post messages as well. If the origin of the message is not from our source website, then we will do nothing and stop the function.

if (e.origin !== "http://source-website.com") {
    return
}

// [parse data object]

If the message is from our source website, then we will first parse the data from a JSON string to a javascript object. Write the code in the [parse data object] section.

const data = JSON.parse(e.data)

Then we will check if the message has a name field.

if (typeof data.name !== "undefined") {
    // [save in local storage]
}

If it has, then we will set it in the destination website's local storage. Also, we will log the message that will be displayed in the source website's console tab. The following code goes in the [save in local storage] section:

localStorage.setItem("name", data.name)
console.log("Name is set: " + data.name)

Save the destination website file and refresh the source website. The name will be set, and you will see that message in your source's browser console. If you open your destination website's browser console and type localStorage.getItem("name"), you will see the name that you can send from the source website. Then you can use that value in the destination website in any way you like.

Complete code: Share local storage between websites in Javascript

<!-- source.php -->

<iframe src="http://destination-website.com/saveLocalStorage.php" style="display: none;"></iframe>

<script>
    window.addEventListener("load", function () {
        const iframe = document.querySelector("iframe")
        const wind = iframe.contentWindow
        
        const data = {
            name: "adnan-tech.com"
        }
        
        wind.postMessage(JSON.stringify(data), "*")
    })
</script>
<!-- http://destination-website.com/saveLocalStorage.php -->

<script>
    window.addEventListener("message", function (e) {
        if (e.origin !== "http://source-website.com") {
            return
        }
        
        const data = JSON.parse(e.data)
        
        if (typeof data.name !== "undefined") {
            localStorage.setItem("name", data.name)
            console.log("Name is set: " + data.name)
        }
    })
</script>

So that's how you can share local storage value from one website to another using Javascript. If you face any problems in following this, kindly do let me know. Check out our more tutorials on Javascript.

[wpdm_package id='1801']

Deploy Node JS app on VPS or Dedicated server

In this article, we are going to teach you how you can deploy the Node JS app on a VPS (Virtual Private Server) or a dedicated server. Make sure you have Node JS, NPM (Node Package Manager), and PM2 (Process Manager) installed, you can run the following commands to see if they are installed.

node -v
npm -v
pm2

If any of them is not installed on your server, you can simply chat with your hosting provider’s customer support center or open a ticket and ask them to install these for you. The main thing you are going to need for deployment is pm2.

Install Node JS

To install specific version of Node JS, first you need to install NVM (Node Version Manager).

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash

Then you need to reload your shell configurations.

source ~/.bashrc

You can verify your installation of NVM by running the following command.

nvm -v

It will show you your NVM version (0.39.5 at the time of writing this). Then run the following command to list all available Node JS versions.

nvm ls-remote

You can install the specific version of Node JS by running:

nvm install 22.11.0

Here, 22.11.0 is the latest LTS version at the time of writing this post. You can set it accordingly. In order to make your NVM to use the installed version by default, you can run the following 2 commands.

nvm default 22.11.0
nvm alias default 22.11.0

If everything goes well, you can run the following command to verify that the Node JS has been successfully installed in your VPS or dedicated server.

node -v

Install PM2 (Process Manager)

If pm2 is not installed in your server, you can install is by running the following command:

npm install -g pm2

Creating a Node JS server

First, create a sub-domain for example “node.adnan-tech.com”. It will also create a directory for this sub-domain. Then create a simple Node JS app in it by running the following command in your cPanel terminal:

npm init

Press Enter key for all questions to set the default values. Then install the following modules:

npm install express http cors express-formidable socket.io

Inside the directory created for the sub-domain, create a file named “server.js” and write the following code in it:

server.js

const express = require("express")
const app = express()

const cors = require("cors")
app.use(cors())

const expressFormidable = require("express-formidable")
app.use(expressFormidable())

const http = require("http").createServer(app)
const socketIO = require("socket.io")(http, {
	cors: {
		origin: "*"
	}
})

const port = process.env.PORT || 3000

http.listen(port, function () {
	console.log("Server started at port: " + port)

	socketIO.on("connection", function (socket) {
		console.log("User connected: " + socket.id)

		// [listen events here]
	})
	
	app.get("/", function (request, result) {
	    result.send("Hello world !")
	})
	
	// [create API here]
})

Then you need to tell your Node JS app that you will be using server.js as the main file. So open your package.json file and set the main key’s value to “server.js” as follows:

package.json

"main": "server.js",

Deploy the Node JS app

Now to start the server, first, open your “Terminal” from cPanel, and go to your subdomain by running the command:

cd yoursubdomain.com

Or whatever your subdomain path is. Then run the following command to start the server:

pm2 start server.js --name "Name of your app" --watch

–name is used to set a specific name for your app.

–watch is used to automatically restart the server if there is any change in the server.js file.

List all processes using pm2

You can view the list of all processed from the command:

pm2 list

If the write the URL https://yoursubdomain:3000/ in the browser, you will see the text “Hello world”. It means your Node JS server is successfully deployed on your VPS or dedicated server.

Create an API in Node JS

Now write the following code to create an API in the [create API here] section:

app.post("/myAPI", function (request, result) {
    const name = request.fields.name
    
    result.json({
        status: "success",
        message: "API has been called.",
        data: "Your name is " + name
    })
})

Then create an index.html file anywhere in your domain and write the following code to it to call an AJAX to this Node JS server.

index.html

<script>
	const ajax = new XMLHttpRequest()
	ajax.open("POST", "https://yoursubdomain:3000/myAPI", true)

	ajax.onreadystatechange = function () {
		if (this.readyState == 4) {
			if (this.status == 200) {
				console.log(this.responseText)
			}
		}
	}

	const formData = new FormData()
	formData.append("name", "Adnan")
	ajax.send(formData)
</script>

Open your browser console tab and you will see the message “Adnan”. Try changing the value in the “name” field in the formData object and refresh the page, you will now see your updated value.

Socket IO

You can also connect sockets to this Node JS server. In your index.html file, first, include the socket IO JS library using CDN:

<script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>

Then write the following Javascript code to connect the client with the server:

<script>
	const socketIO = io("https://yoursubdomain:3000")
</script>

After that, emit a simple event to the server:

// index.html

socketIO.emit("newEvent", { name: "Adnan" })

Then in your server.js, write the following code in place of the [listen events here] section:

// server.js

socket.on("newEvent", function (data) {
	socket.emit("newEvent", data)
})

And finally, on your client side, you need to listen to this event and display a message in the browser console:

// index.html

socketIO.on("newEvent", function (data) {
	console.log(data)
})

Refresh your page now and open your browser console. You will now see an object in the console. It means that your Node JS server’s sockets are running fine.

Stop the pm2 process

By default, the pm2 process will keep on running forever. If you want to stop the process, you can simply enter the following command in your cPanel terminal:

pm2 stop "Name of your app"

Run pm2 list and you will now see the status of your process as stopped.

Remove the pm2 process

Similarly, you can remove the pm2 process by running the following command:

pm2 delete "Name of your app"

Run pm2 list and you will no longer see your process in the list.

So that’s how you can deploy a Node JS app on your VPS or dedicated server. Check our tutorial to deploy Node JS app on the Heroku server. If you face any problems in following this, kindly do let me know.

Pass value between components – Vue JS

In this article, we will teach you how to pass value between 2 components in Vue JS. We will be using Vuex for this.

Video tutorial

Create a store

First, you need to create a store. To do this, install a module named vuex. Run the following command in your terminal:

npm install vuex

After that, you must create a folder named “vuex” in your “src” folder. Then, create a file named “store.js” inside “vuex” folder. Following will be the content of store.js file:

import { createStore } from "vuex"

export default createStore({
	state() {
		return {
			variable: 123
		}
	},

	// [mutations goes here]

	// [getters goes here]
})

“variable” will be the variable that you need to pass between components. You can set its default value here.

Pass value to component 1

Let’s say you want to display the value in component 1. So I am going to create a simple paragraph tag to display a value.

<p v-text="variable"></p>

And we need to make this variable a computed property. So we will write the following Javascript code in component 1.

import store from "../vuex/store"

export default {
	computed: {
		variable: function () {
			return store.getters.getVariable
		}
	}
}

First, we are including the store file that we created in the previous step. Our component is in “src/components” folder, and store file is in “src/vuex”, so we have to move a step back using “../”.

Then we are created a computed property “variable”, and it returns the “getVariable” value from the store getters object. The getters is the built-in property in Vuex store. And “getVariable” will be a function that we need to create in our store file.

So write the following code in the [getters goes here] section of store.js file:

getters: {
	getVariable: function (state) {
		return state.variable
	}
}

It accepts a state object as an argument. And with this object, you can call the variables in the state() function create in the first step. Run the component 1 now and you will see the value “123” in your paragraph.

Pass value from component 2

Now support in your component 2, you want to change its value and it should reflect in component 1 as well. First, write the following code in the [mutations goes here] section of store.js file:

mutations: {
	setVariable: function (state, newValue) {
		state.variable = newValue
	}
}

It accepts state and newValue as arguments. With the state object, you can change the values. And newValue is simply the new value that will be passed to it.

To call this function, we are going to create a simple button in our component 2.

<button type="button" v-on:click="updateVariable">Update variable</button>

Then we are going to create this method in our Javascript and call the setVariable function from our store file.

import store from "../vuex/store"

export default {
	methods: {
		updateVariable: function () {
			store.commit("setVariable", 567)
		}
	}
}

commit function from Vuex store will call the function created in mutations object. Second parameter will be the new value. Run the app now and click on the button. As soon as you press the button, you will notice that the variable value in 1st component will automatically get updated.

Source code

[wpdm_package id=’1733′]

Conclusion

So you have learned how to create a Vuex store in Vue JS, and how to pass value between components in Vue JS. If you face any problems in following this, kindly do let me know. We also created a chat application where we implemented this technique, so you will know how it is used practically in projects.

Promise and async await in Javascript

Promises are created in Javascript to prevent the callback hell. But it came with its own problems and complexities. To deal with them, we were introduced to async and await commands. So today, we are going to teach you, how you can create a promise in Javascript, and how to call it using async/await command.

Video tutorial

Basic example of promise with async await

Let’s start with a basic example. We are going to create a simple Javascript function that will return a promise. The promise will call the callback function with a string value.

function doSomething() {
	return new Promise(function (callBack) {
		callBack("Response")
	})
}

To use the async and await commands, we need to create another function that will use these commands.

async function callDoSomething() {
	const response = await doSomething()
	console.log(response)
}

The function name will be prepended with async and the function that returns a promise i.e. doSomething() will be prepended with await command. In this case, the response variable should print “Response” that was called at line 3 of previous code.

Finally, we simply need to call the callDoSomething() to run the code.

callDoSomething()

Run the code now, and you will see “Response” in your browser console. Try change the string value of callBack parameter and you will see that it will be reflected in response variable in callDoSomething() function.

Practical example

Let’s move to a more practical example. Let’s say you want to call an AJAX request from the promise. And instead of receiving the response in a callback, you want to receive it using async/await command.

So go ahead and change the doSomething() function to the following:

function doSomething() {
	return new Promise(function (callBack) {
		const ajax = new XMLHttpRequest()
		ajax.open("POST", "server.php", true)

		ajax.onreadystatechange = function () {
			if (this.readyState == 4) {
				if (this.status == 200) {
					callBack(this.responseText)
				}
			}
		}

		const formData = new FormData()
		ajax.send(formData)
	})
}

The code is self-explanatory but if you want to know more about the XMLHttpRequest, we have created a separate detailed tutorial on this.

Then we will create a simple PHP file that will return a simple string as response. Create a new file named server.php and write the following code in it:

<?php

sleep(1);

echo "Response from server";
exit();

We are calling the sleep() function just to give it 1 second delay. If you run the code now, you will start seeing “Response from server” in the browser console.

[wpdm_package id=’1720′]

Compress image in Node JS

In this tutorial, we are going to teach you, how you can compress image in Node JS. You can download and install Node JS from their official site.

Video tutorial: Compress image in Node JS

First, create a new folder. Open CMD in it. And run the following commands:

> npm init
> npm install express http

Then, create a file named “server.js” and write the following code in it:

const express = require("express")
const app = express()
const http = require("http").createServer(app)

// [other modules]

const port = process.env.PORT || 3000

http.listen(port, function () {
	console.log("Server started running at port: " + port)

	// [post route goes here]

	// [get route goes here]
})

Then run the following commands in your terminal:

> npm install -g nodemon
> nodemon server.js

You will see a message saying the “Server started running at port: 3000”. You can access your server from the following URL:

http://localhost:3000

Now, we need to install the module for displaying views. And to get input from form fields. So, install the following modules:

> npm install ejs fs express-formidable

EJS module is used for displaying the HTML files. FS stands for File System, this module is used to handle files. And “express-formidable” is used for getting values from the input field. Make sure to run the “nodemon server.js” command again.

Install compress image module in Node JS

To install a module to compress image in Node JS, you need to run the following command in your terminal:

> npm install pngquant-bin@6.0.1 gifsicle@5.2.1 compress-images fs

Then, we need to include those modules in our project. So write the following lines in the [other modules] section:

const compressImages = require("compress-images")
const formidable = require("express-formidable")
app.use(formidable())

const fileSystem = require("fs")
app.set("view engine", "ejs")

Now, write the following lines in the [get route goes here] section:

app.get("/", function (request, result) {
	result.render("index")
})

After that, you need to create a folder named “views” at the root of your project. And in that folder, create a file named “index.ejs”. Following will be the code of “index.ejs”:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		<title>Compress image</title>
	</head>

	<body>
		<form method="POST" action="/compressImage" enctype="multipart/form-data">
			<input type="file" name="image" accept="image/*" required />
			<input type="submit" value="Compress image" />
		</form>
	</body>
</html>

It will display a simple HTML form with an input field and a submit button. Then, you need to create a POST route that will handle this request. The following code goes in the [post route goes here] section of the “server.js” file:

app.post("/compressImage", function (request, result) {
    const image = request.files.image
    if (image.size > 0) {

        if (image.type == "image/png" || image.type == "image/jpeg") {
            fileSystem.readFile(image.path, function (error, data) {
                if (error) throw error

                const filePath = "temp-uploads/" + (new Date().getTime()) + "-" + image.name
                const compressedFilePath = "uploads/"
                const compression = 60
                
                fileSystem.writeFile(filePath, data, async function (error) {
                    if (error) throw error
                    
                    compressImages(filePath, compressedFilePath, { compress_force: false, statistic: true, autoupdate: true }, false,
                        { jpg: { engine: "mozjpeg", command: ["-quality", compression] } },
                        { png: { engine: "pngquant", command: ["--quality=" + compression + "-" + compression, "-o"] } },
                        { svg: { engine: "svgo", command: "--multipass" } },
                        { gif: { engine: "gifsicle", command: ["--colors", "64", "--use-col=web"] } },
                        async function (error, completed, statistic) {
                            console.log("-------------")
                            console.log(error)
                            console.log(completed)
                            console.log(statistic)
                            console.log("-------------")

                            fileSystem.unlink(filePath, function (error) {
                                if (error) throw error
                            })
                        }
                    )

                    result.send("File has been compressed and saved.")
                })

                fileSystem.unlink(image.path, function (error) {
                    if (error) throw error
                })
            })
        } else {
            result.send("Please select an image")
        }
    } else {
        result.send("Please select an image")
    }
})

The last thing you need to do is to create two folders named “uploads” and “temp-uploads” at the root of your project. Here, all compressed images will be stored.

This will compress the image up to 60%. You can now try to select an image from the input file and hit “Compress image”. You will see a success message if everything goes right. And you will see your compressed image in the “uploads” folder.

Real-world example

We implemented this compression in one of our projects, so you can get the real-world example of image compression in Node JS.

So that’s how you can compress an image in Node JS. If you face any problems in following this, kindly do let us know.

Download source code

[wpdm_package id=’1704′]