Usage scenarios of JavaScript try/catch/finally

The ry/catch/finally statement is used to handle error messages that may appear in the code.
Errors may be syntax errors, usually coding errors or typos made by the programmer. It could also be a typo or a missing feature in the language (possibly due to browser differences).
The try: statement allows us to define a block of code that is tested for errors while executing.
The catch: statement allows us to define the code block that is executed when an error occurs in the try code block.
finally: The statement will be executed after try and catch regardless of whether there is an exception.
Note: Both catch and finally statements are optional, but you must use at least one when using a try statement.
Tip: When an error occurs, JavaScript stops execution and generates an error message. Use the throw statement or console.error() to create custom messages (throw exceptions). If you use throw with try and catch, you can control the error message output by the program.

When there is a return in try or catch, execute finally first and then execute return; and the values of variables in try and catch cannot be modified in finally.

try {<!-- -->
  //Run (error)
  throw 'Exception information';
} catch (error) {<!-- -->
  //capture
} finally {<!-- -->
  //Must be executed eventually. Generally used to release resources, such as database connections, file streams, etc.
}

**Scenario 1: **try/catch/throw performs process (if) control and throws customized exception information.

function getStringToArray(str){<!-- -->
  try {<!-- -->
    if(str === undefined || str === null){<!-- -->
      //After throwing the exception, stop downward execution and run the catch code directly.
      throw "An error occurred! This is not a string, undefined / null does not have any attributes";//throw statement: Create a custom error and throw an exception
    }
    if(Object.prototype.toString.call(str) === "[object Number]"){<!-- -->
      //After throwing the exception, stop downward execution and run the catch code directly.
      throw "Error! This is not a string, and the numeric type does not have the split method attribute";
    }
    var arr = str.split(',');
    return arr;
  } catch (error) {<!-- -->
    console.error(error);//Output custom exception information
    return [];
  }
}

getStringToArray(undefined);//Output: [Error! This is not a string, undefined / null does not have any attributes]
getStringToArray(null);//Output: [Error! This is not a string, undefined / null does not have any attributes]
getStringToArray(123);//Output: [Error! This is not a string, and the numeric type does not have the split method attribute]
getStringToArray("basketball, football, volleyball");

Scenario 2: Terminate the forEach loop. Use try/catch/throw to disable code execution. Note: Promise.reject(error message’) can only prevent further execution within the current function.

var arr = [1,2,3,4,5];
try {<!-- -->
  arr.forEach(element => {<!-- -->
    if(element === 3){<!-- -->
      throw 'Loop terminated';
    }
    console.log('Number: ', element);
  });
} catch (error) {<!-- -->
  console.error(error);//Output exception information: loop terminated
}

**Scenario 3:** In the Vue project, the component address of the large screen on the homepage is configurable. In order to prevent the user from entering the wrong component address, the page routing component cannot be loaded and the page cannot be entered. You need to preload it once with require, catch it with try/catch, and reassign the available routing component address if the exception occurs.

//Menu data returned by the backend
var menuData = [
  {<!-- -->
    "path": "/dashboard/analysis",
    "component": "dashboard/Analysis",
    "route": true,
    "meta": {<!-- -->
      "external": false,
      "keepAlive": false,
      "icon": "home",
      "permissionList": [
        {<!-- -->}
      ],
      "componentName": "Analysis",
      "title": "Homepage"
    },
    "name": "dashboard-analysis",
    "id": "1374671776843169794"
  },
  //{...},
  //{...},
  //{...},
];
menuData.forEach(element => {<!-- -->
  //Preload the large screen component address to prevent invalid component addresses from causing the page to be white and unable to enter the system.
  if (element.path === "/dashboard/analysis") {<!-- -->
    try {<!-- -->
      require('@/views/' + element.component);//Test loading of large screen components
    } catch (error) {<!-- -->
      console.error(`Invalid large screen component address configured [${<!-- -->element.component}]:`, error);
      element.component = 'dashboard/*******';//Reset the effective large screen component
    }
  }
});

//Vue component, part of the code for component address input box verification is as follows
export default {<!-- -->
  data() {<!-- -->
    return {<!-- -->
      rules: {<!-- -->
        component: [
          {<!-- -->
            required: true,
            message: 'Please enter the component address',
            trigger: 'change'
          },
          {<!-- -->
            validator(rule, value, callback) {<!-- -->
              if (value) {<!-- -->
                try {<!-- -->
                  require('@/views/' + value);//Test loading the large screen component
                  return callback();
                } catch (error) {<!-- -->
                  //The component does not exist in the code
                  return callback(new Error('The component address is incorrect'));
                }
              } else {<!-- -->
                return callback(new Error('The component address cannot be empty'));
              }
            }, trigger: 'blur'
          },
        ]
      }
    }
  },
  methods: {<!-- -->}
}

**Scenario 4:** In the input box, the user enters a letter expression. If you want to know whether the expression is correct, you can use try/catch/eval to process the expression.

var express = 'a + b + (c * e)';//The expression entered by the user in the input box
var arr = "abcdefghijklmnopqrstuvwxyz".split("");
arr.forEach((element,index) => {<!-- -->
  express = express.replaceAll(element,index + 1);//Replace letters with numbers,
});

try {<!-- -->
  eval(express); // Operate strings (numbers), if legal, pass
} catch (error) {<!-- -->
  //Does not pass verification
  new Error(`Calculation formula is abnormal and cannot be calculated after conversion`);
}

**Scenario 5:** Enter the json data string (request header) into the input box, and try/cath captures the exception for verification.

var str = "{a:111,b:}";
try {<!-- -->
  JSON.parse(str);//
} catch (error) {<!-- -->
  console.log(new Error(`json data is incorrect`));
}

**Scenario 6:** The data is uncontrollable and error-prone, so you need to add try/cath to catch exceptions.

try {<!-- -->
  var data = [];//The backend return is complex and uncertain
  for (let i = 0; i < data.length; i + + ) {<!-- -->
    const element = data[i];
    //Data processing and conversion may cause errors
  }
} catch (error) {<!-- -->
  alert('Data processing error!');
}

Uncaught exception. Note: The outer try/catch cannot capture exceptions within asynchronous queue microtasks and macrotasks. To capture exceptions within macrotasks, the try/catch code can only be written within the microtask and macrotask codes. If the setTimeout method is executed within the scope of the try block, the error err information is thrown out from the setTimeout timer. It cannot be captured outside the catch, because setTimeout is executed on a temporary register, so the context is not processed on a stack. The error err Cannot be captured.

try {<!-- -->
  (async function(){<!-- -->
    //After adding async, try cannot catch exceptions in the function. After removing async, catch will catch the exception.
    var num = undefined;
    num.toString();//Error code, exception thrown by the browser
  })();
} catch (error) {<!-- -->
  console.error('Exception output:',error); //Exception not caught
}
function getData() {<!-- -->
  return new Promise((resolve, reject) => {<!-- -->
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://cdn.bootcss.com/vue/2.6.14/vue.min.js', false);
    xhr.onreadystatechange = function () {<!-- -->
      //Asynchronous code, cannot catch exceptions (macro task)
      // readyState == 4 indicates that the request has been completed
      if (xhr.readyState == 4) {<!-- -->
        if (xhr.status == 200 || xhr.status == 304) {<!-- -->
          resolve();
          var str = undefined;
          str.split(',');//Error code, exception thrown by the browser
        }
      }
    }
    xhr.send();
  });
}
(async function () {<!-- -->
  try {<!-- -->
    setTimeout(() => {<!-- -->
      //Exceptions within the timer are not caught (macro task)
      var str = undefined;
      str.join(',');//Error code, exception thrown by the browser
    }, 100);

    Promise.resolve().then(() => {<!-- -->
      //then (microtask)
      var arr = null
      arr.push(111);//Error code, exception thrown by the browser
    });

    await getData().then(() => {<!-- -->
      //In the await then function, exceptions can be caught. The processing context on the same stack can catch exceptions.
      var num = undefined;
      num.toString();
    });
  } catch (error) {<!-- -->
    console.error('Exception output:', error);//No output
  }
})();