-1
\$\begingroup\$

Using visual studio I created a snippet which helps me surround my already written or new code into a try-catch-finally block. I use axios for REST so there had to be separate error handling method so that users can cleanly view the error result and report it to the support team.

Code:

try {

    //Start the loading bar so user can know something is running in background    
    this.$store.commit("isLoading", true);

    //Some axios code runs here...
    const response = await this.axios.post(process.env.VUE_APP_API_ExampleAPI, { param1: 'blaa', param2: 'blaa2' });

    //Once done result is going to be shown in a modal using vuex as store
    //200 response requests will always return the response in the format of an object and message containing in "message" parameter
    this.$store.commit("successMessage", response.data.message);
    //Now user is shown the modal
    this.$store.commit("successModal", true);
}
catch (error) {
    //In case the error is via axios request
    if (error.isAxiosError) {
        var concatMessages = '';
        Object.entries(error.response.data.errors).forEach(([key, value]) => concatMessages += value);
        this.$store.commit("errorMessage", concatMessages);
        this.$store.commit("errorModal", true);
    }
    //Other non-axios errors i.e. syntax error, code error etc...
    else {
        this.$store.commit("errorMessage", error.toString());
        this.$store.commit("errorModal", true);
    }
}
//Finally block stops the progress bar loading indicating background process isn't anymore
finally {

    this.$store.commit("isLoading", false);
}

Now I feel like there is too much code in it despite it helps in development. I mean it is repeated in almost every function/method.

There has to be a way to reduce this code or improve it to avoid repetition in most of the functions but I am not sure what it could be.

\$\endgroup\$
  • 2
    \$\begingroup\$ Welcome to Code Review! At the moment there is not really context to show how this code is used. That makes it hard for reviewers to give you meaningful and targeted feedback. \$\endgroup\$ – AlexV Jul 28 '19 at 16:50
2
\$\begingroup\$

Refactoring to DRY Code

In order to avoid repetition, we could create a couple of reusable functions to enable your functions to all use the same pattern.

The pattern:

  • start loading
  • await operation
  • loading completed
  • notify success
  • on error: notify error

buildErrorMessage

Let's start by making a function that builds an error message given an error.

function buildErrorMessage(error) {
  if (error.isAxiosError) {
    let concatMessages = '';
    Object.entries(error.response.data.errors)
      .forEach(([key, value]) => concatMessages += value);
    return concatMessages;
  }
  return error.toString();
}

to avoid writing code as..

if (error.isAxiosError) {
    var concatMessages = '';
    Object.entries(error.response.data.errors)
      .forEach(([key, value]) => concatMessages += value);
    this.$store.commit("errorMessage", concatMessages);
    this.$store.commit("errorModal", true);
}
//Other non-axios errors i.e. syntax error, code error etc...
else {
    this.$store.commit("errorMessage", error.toString());
    this.$store.commit("errorModal", true);
}

executeInBackground

Now we could provide a wrapper function to execute other functions in the background, updating the store before, after and on error of the operation.

async function executeInBackground(operation) {
  try {
    this.$store.commit("isLoading", true);
    const response = await operation();
    this.$store.commit("successMessage", response.data.message);
    this.$store.commit("successModal", true);
  }
  catch (error) {
    const errorMessage = buildErrorMessage(error);
    this.$store.commit("errorMessage", errorMessage);
    this.$store.commit("errorModal", true);
  }
  finally {
    this.$store.commit("isLoading", false);
  }
}

This part..

  const response = await operation();

Is a generic replacement for your code:

//Some axios code runs here...
const response = await this.axios.post(process.env.VUE_APP_API_ExampleAPI, 
    {param1: 'blaa', param2: 'blaa2' });

By replacing the specific operation with a template place holder, we can avoid repetition for every other operation that needs to follow the same pattern.


entrypoint functions

And finally, we create a function that handles the stuff from the OP.

async function processExample() {
  await executeInBackground(() 
    => this.axios.post(process.env.VUE_APP_API_ExampleAPI, { 
      param1: 'blaa', param2: 'blaa2' }));
}

This way, you avoid redundant error handling, and update the store in a consistent fashion. Each new function that requires the same behavior should just call await executeInBackground with the operation that is required.

Suppose you have another function, it gets apparent that code duplication can be avoided:

async function processSomethingElse() {
  await executeInBackground(() 
    => this.axios.post(process.env.VUE_APP_API_ExampleAPI, { 
      param1: 'other', param2: 'other2' }));
}

And thus we have established DRY code.

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ Thank you, this improves my code. \$\endgroup\$ – Suleman Jul 28 '19 at 20:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.