5

Handling Node.JS as an Asynchronous Application with Error Handling

 3 years ago
source link: https://hackernoon.com/handling-nodejs-as-an-asynchronous-application-with-error-handling-hi3p355b
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Handling Node.JS as an Asynchronous Application with Error Handling

@th3n00bc0d3rMuhammad Bilal

Founder, Full Stack & Hardware Engineer, Philosopher

This article is about implementing asynchronous calls in JavaScript and Node.JS.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

In this article, you will learn how to implement the following coding practices

0 reactions
heart.png
light.png
thumbs-down.png
money.png
  • differentiate between a Synchronous and Asynchronous Call
  • execute functions in Concurrency
  • execute Promises in an Asynchronous Call
  • wait for a function to execute before continuing
  • prevent a Node.JS Application from Breaking
  • handle errors of consecutive running functions

Asynchronous calls are the knife and butter for a JavaScript developer. JavaScript, as a language, is a single-threaded engine which means that one thing can happen at one time. This is called single threading. This does bring in simplicity but holds one back from performing time-consuming operations. The time for an operation in a web application is termed as its operation cost. For Javascript developers, pushing an application to be performative means that we reduce this operation cost to as low as possible. This process of reducing the cost is called optimization of an application. Therefore, to run such concurrency in a Javascript code, we use asynchronous calls.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

What is a synchronous call?

A synchronous call the code that is being executed, i.e the program itself, waits for each line to run before moving on wards to the end of the program. It can be further illustrated by stating that each operation will complete before starting the next operation. The time needed to execute the operation is known as the latency or lag the user perceives. The order of the code matters in synchronous calls. Most of the code that you have written in Javascript is running as synchronous.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Sample Code of a Synchronous Call

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const printToConsole = (msg) => {
  console.log(msg);
}

const myFunctionOne = () => {
  printToConsole('Hello From Soshace, I am Number One');
}

const myFunctionTwo = () => {
  printToConsole('Hello From Soshace, I am Number Two');
}

const displayMessages = () => {
  myFunctionOne();
  myFunctionTwo();
  printToConsole('Dude, I am from the Third');
}

displayMessages();

Output of the Code

0 reactions
heart.png
light.png
thumbs-down.png
money.png

To better understand the output of the code, Javascript creates an environment which calls the main() function. The main() function is the single-core thread of Javascript itself. This environment is like a stack on top of which the displayMessage() function is added.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

The displayMessage() function holds a set of functions. The first one that is executed is myFunctionOne() therefore it is added on the top of the execution stack. myFunctionTwo() functions follows and the last one to get executed is printToConsole() function. At this point, no function is executed — only queued, until no function is left in the program.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Once there are no functions left, the queue starts emptying up one by one starting from the bottom which, in this case, first executes the main() thread and then the displayMessages() function.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

The first output in the console will be from myFunctionOne(), which is “Hello from Soshace, I am Number One”. Then, the second console output will be from myFunctionTwo(), which is “Hello from Soshace, I am Number Two”. After the last function, which is printToConsole() is out, it will finally output to the console “Dude, I am from the Third”. This environment created by Javascript is known as an Execution Context and the queuing process is known as the Call Stack.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

What is an Execution Context?

JavaScript creates an environment where it examines the code and performs basic execution tests for any possible errors and then executes the code. This is done as a global context so, if a new function gets executed, it will repeat the process. This environment is called the execution context.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

What is a Call Stack?

JavaScript creates a stack, where it keeps a record of the functions that are being run as code. This stack is a Last-In-First-Out (LIFO). When JavaScript runs the code, it adds the function into this stack and starts carrying it out. Any function further more down the line is pushed to it and carried out in order.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

The diagram illustrates the creation of the execution context, which is the main(), and as it starts pouring in the function until it runs out of function to run.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

The Asynchronous Call

In the following code, we are creating a delay function. The delay function promises us a value after it is executed in the console. A promise with respect to the delay function is an object that will return us a value somewhere in the future. Next, we have written an async function that will execute the promises and at the end should print us a message.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const myDelay = (ms) => {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log('Delayed');
            resolve();
        }, ms);        
    })
}

const myFunction = async () => {
    myDelay(2000);
    myDelay(2000);
    console.log('End of the Line');
}

myFunction();

Output

0 reactions
heart.png
light.png
thumbs-down.png
money.png

As you can see, the code was executed in concurrency where it did not wait for the delay function to execute and moved to the end of the code to complete its call stack. This can be troublesome in use cases, where you want to wait for a value from a network call before proceeding on with the code. To fix such an issue we use the ‘await’ keyword in JavaScript.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const myDelay = (ms) => {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log('Delayed');
            resolve();
        }, ms);        
    })
}

const myFunction = async () => {
    <strong>await</strong> myDelay(2000);
    <strong>await</strong> myDelay(2000);
    console.log('End of the Line');
}

myFunction();

Output

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Now, our JavaScript will wait for the function to complete and keep its promise before rushing into completing the script. This is highly effective in doing network calls and waiting for data to form from the network. Once you receive the data, then you can process the data received from the network call and proceed with your application. It also ensures that nothing is missed or skipped during the execution of the code.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Handling Errors

We are now creating a function that will help us simulate an error.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const simulateError = async () => {
    throw new Error('Failure!')
}

simulateError();

Output

0 reactions
heart.png
light.png
thumbs-down.png
money.png

This has literally broken our application, now, if this was a production-level application, one would lose all contact to the backend API and lose the server from serving people currently using the application which nobody wants.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const simulateError = async () => {
    throw new Error('Failure!')
}

simulateError()
.catch(
  (error) => {
    console.log(error)
});

The catch clause will ensure that our application is not broken from serving our clients. Let’s look at the output.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

As you can see, it has warned us of the same danger but has kept our application alive. This is helpful when working with production level apps that should not break out of the process and require manual restarting.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Error Handling in a Chain of Promise Events

A typical case would be of running multiple await statements and having a couple of them produce an error. The code can become really messy to handle it but there is a better way of doing it with a much cleaner code organization.

0 reactions
heart.png
light.png
thumbs-down.png
money.png
const simulateError = async () => {
    throw new Error('Failure!')
}
const produceMultipleErrors = async _ => {
  const one = await simulateError()
  const two = await simulateError()
  const three = await simulateError()
}

produceMultipleErrors()
    .catch(
        (error) => {
            console.log(error)
        });

The above code will allow us to compile errors into a single stack and produce it as all the calls are asynchronously executed. This is a great error handling technique that comes in handy when writing bigger applications. Error handling is an important part of any application which a lot of developers overlook.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Recently, I did come up with various situations when building up my own social media, but this allowed me to solve the hiccups in my code in a much cleaner and more precise way. I think the use of asynchronous functions in your code helps you in making your application mode dynamic and robust, therefore promising that your application would eventually survive the hardened road bumps of the development stage into the production stage.

0 reactions
heart.png
light.png
thumbs-down.png
money.png

Previously published at https://dev.to/th3n00bc0d3r/handling-node-js-as-an-asynchronous-application-with-error-handling-1840

0 reactions
heart.png
light.png
thumbs-down.png
money.png
6
heart.pngheart.pngheart.pngheart.png
light.pnglight.pnglight.pnglight.png
boat.pngboat.pngboat.pngboat.png
money.pngmoney.pngmoney.pngmoney.png
Share this story
Join Hacker Noon

Create your free account to unlock your custom reading experience.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK