Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 18, 2021 08:58 pm GMT

Callback hell OR try catch hell (tower of terror)

What are "Callbacks"?

A callback function is usually used as a parameter to another function.

The function that receives callback function is normally fetching data from a database, making an API request, downloading a file, which usually takes a while.

Assume getting some data from the API and the request takes around 2 seconds to complete.

Now, you can either wait for the API call to complete and then display your UI,

OR, you show everything else and show a loader where the API data needs to be shown.

In the API function, we pass some sort of "call back" function that replaces loader with actual data, so once the response is received from API

It calls the callback function with the data and, then our callback function replaces the loader.

Let's see this in action:

function getDataFromAPI(callbackFunction) {  fetchSomeData().then((data) => {    callbackFunction(data);  });}getDataFromAPI(function replaceLoaderWithData(data) {  // your awesome logic to replace loader with data});

OR

// from w3schoolsfunction myDisplayer(sum) {  document.getElementById('demo').innerHTML = sum;}function myCalculator(num1, num2, myCallback) {  let sum = num1 + num2;  myCallback(sum);}myCalculator(5, 5, myDisplayer);

Okay, you already know this. We're not learning what callbacks are.

What is "callback hell"?

If your application logic is not too complex, a few callbacks seem harmless.
But once your project requirements start to increase, you will quickly find yourself piling layers of nested callbacks.

Like this:

getAreas(function (areas) {  getTowns(function (towns) {    getCities(function (cities) {      getCountries(function (countries) {        getContinents(function (continents) {          getPlanets(function (planets) {            getSolarSystems(function (solarSystems) {              getGalaxies(function (galaxies) {                // Welcome to the callback hell...              });            });          });        });      });    });  });});

Of course, we can use JavaScript's Promise and move to .then & .catch.

getAreas().then(function (areas) {  getTowns().then(function (towns) {    getCities().then(function (cities) {      getCountries().then(function (countries) {        getContinents().then(function (continents) {          getPlanets().then(function (planets) {            getSolarSystems().then(function (solarSystems) {              getGalaxies().then(function (galaxies) {                // Welcome to the callback hell AGAIN...              });            });          });        });      });    });  });});

Congrats! Welcome to Callback Hell.

Callback Hell, also known as Pyramid of Doom, is a slang term used to describe an unwieldy number of nested if statements or functions.

Async Await to the rescue!

Async await feels like heaven because it avoids the callback hell or pyramid of doom by writing asynchronous code in a clean line-by-line format.

The above code changes to this:

// assuming the environment supports direct async functionconst areas = await getAreas();const towns = await getTowns();const cities = await getCities();const countries = await getCountries();const continents = await getContinents();const planets = await getPlanets();const solarSystems = await getSolarSystems();const galaxies = await getGalaxies();// now this... looks awesome!!!

BUT...

This is awesome until error handling comes into play because you end up with the try-catch tower of terror!

All your beautiful one-liners magically expand to at least five lines of code...

// assuming the environment supports direct async functiontry {  const areas = await getAreas();} catch (err) {  // handleError(err)}try {  const towns = await getTowns();} catch (err) {  // handleError(err)}try {  const cities = await getCities();} catch (err) {  // handleError(err)}try {  const countries = await getCountries();} catch (err) {  // handleError(err)}// ... and so on.

You can find yourself an easy way which is simply by appending the catch method to the end of each promise.

// assuming the environment supports direct async functionconst areas = await getAreas().catch((err) => handleError(err));const towns = await getTowns().catch((err) => handleError(err));const cities = await getCities().catch((err) => handleError(err));const countries = await getCountries().catch((err) => handleError(err));const continents = await getContinents().catch((err) => handleError(err));const planets = await getPlanets().catch((err) => handleError(err));const solarSystems = await getSolarSystems().catch((err) => handleError(err));const galaxies = await getGalaxies().catch((err) => handleError(err));

This looks better, but! This is still getting repetitive.

Another better option is to create a standardized error handling function.

The function would first resolve the promise then returns an array.

In that array, the first element is the data and the second element is an error.

If there's an error then the data is null and the error is defined, like this:

async function promiseResolver(promise) {  try {    const data = await promise();    return [data, null];  } catch (err) {    return [null, err];  }}

Now when you call this function in your code you can destructure it to get a clean one-liner with error handling,
Or use a regular if statement if you want to do something else with the error.

Your main function would look something like this:

// assuming the environment supports direct async functionconst [areas, areasErr] = await promiseResolver(getAreas);const [towns, townsErr] = await promiseResolver(getTowns);const [cities, citiesErr] = await promiseResolver(getCities);if (citiesErr) {  // do something}const [countries, countriesErr] = await promiseResolver(getCountries);const [continents, continentsErr] = await promiseResolver(getContinents);const [planets, planetsErr] = await promiseResolver(getPlanets);const [solarSystems, solarSystemsErr] = await promiseResolver(getSolarSystems);const [galaxies, galaxiesErr] = await promiseResolver(getGalaxies);if (galaxiesErr) {  // do something}// ... and so on.

That's all folks! Hope you found this helpful, see you in the next one


Original Link: https://dev.to/ovi/callback-hell-or-try-catch-hell-tower-of-terror-5h78

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To