How to improve the robustness of code

Posted by edawg on Sun, 02 Jan 2022 19:00:22 +0100

Robustness means that the program can still run normally when encountering input, errors and exceptions outside the specification. In short, robust code has strong adaptability and will not cause program crash because of some exceptions.

 

The non robust front-end code is reflected in:

 

  • When the interface returns an exception or an error, the page will be blank.

 

  • When the user does some unconventional operations, the page is white.

 

1, How to write robust front-end code

 

 

To write robust front-end code, it is necessary to deal with input, errors and exceptions outside the specification. Specifically, there are four points:

 

  • Exception handling.

 

  • Input check.

 

  • Writing optimization.

 

  • Third party library selection.

 

Next, let's be specific.

 

(1) Exception handling

 

Without exception handling, it may lead to function error or page white screen. Exception handling can be divided into the following situations.

 

  • Proactive capture of runtime exceptions

 

Use try catch to catch runtime errors in synchronization code. If it is asynchronous code, it needs to be converted into await. For example:

 

try {  doSth()  await doSth2()} catch (e) {  // Handling exception}

 

  • Handle unexpected global runtime exceptions

 

When unhandled JavaScript runtime errors (including syntax errors) occur, window will trigger the error event. Do this:

 

window.addEventListener(  'error',  (e) => {/* Handling exceptions */})

 

When a resource (such as < img > or < script >) fails to load, the element loading the resource will trigger the error event. Do this:

 

const img = new Image();img.addEventListener(  'error',  (e) => {/* Handling exceptions */})img.src = 'xxx'

 

  • Asynchronous code: processing of Promise reject

 

When Promise is reject ed, it can be processed in the second parameter of then or catch. For example:

 

p().then(onSuccess, onReject)p().catch(onReject)

 

If the Promise reject is not processed, the window will trigger the unhandledrejection event. It can be handled uniformly:

 

window.addEventListener(  'unhandledrejection',  (e) => {/* Handling exceptions */})

 

  • General handling of interface error when using Axios

 

You can add the general processing of interface error in the interceptor returned by the Axios interface. For example:

 

axios.interceptors.response.use(function (response) {  return response;}, err => {  // Error reporting processing if (err. Response) {switch (err. Response. Status) {case 400: err. Message = 'request error (400)'; break; case 500: err. Message = 'server error (500)'; break; / /...}} return Promise. reject(error);})

 

  • Exception handling for Vue

 

app.config.errorHandler = (err, vm, info) => {  // Handling exception}

 

  • Exception handling of React

 

The life cycle function ComponentDidCatch of React can catch exceptions of sub components. Therefore, you can wrap a component outside the root component to handle errors. For example:

 

class ErrorBoundary extends React.Component {  componentDidCatch(error, info) {    // Handling exception}

 

use:

 

<ErrorBoundary>  <App /></ErrorBoundary>

 

(2) Input check

 

When the input does not meet the conditions, return as soon as possible or actively report an error. The inputs here include: the return result of the interface, the parameters of the function, the properties of the component, etc.

 

  • Interface return format check

 

The return of the interface will be inconsistent with the expectation of the front end. The reason may be:

 

  • The returned result of the interface changes, but the front end is not notified.

 

  • Some special request parameters cause the return value of the interface to be different from the expected value.

 

Therefore, we need to check the interface return format. Let's take an example:

 

const res = await fetchList()const list = res.map(...)

 

If the interface does not return an array, the program will report an error. Optimization like this can be done:

 

const res = await fetchList()const list = Array.isArray(res) ? res.map(...) : []

 

  • Function parameter check

 

JavaScript is a weakly typed language. The parameters of a function can pass any value or no parameters. Therefore, if function parameters are not checked, there will be some inconsistencies with expectations. For example, it is expected to realize the function of summing two numbers:

 

function sum (a, b) {  return a + b}
sum(3, 4) // 7. As expected, sum() // NaN. Inconsistent with expectation sum ('3 ', 4) /' 34 '. Inconsistent with expectations

 

Check the function parameters and optimize them as follows:

 

function sum (a, b) {  if(isNaN(parseFloat(a)) || isNaN(parseFloat(b))) {    throw 'param error. param should be a num'  }  return parseFloat(a) + parseFloat(b)}

 

TypeScript is recommended. You can use it to check function parameters. The above code is written in TypeScript:

 

function sum (a: number | string, b: number | string) {  return parseFloat(a as string) + parseFloat(b as string)}

 

  • Component property check

 

The component property check is similar to the function parameter check, so I won't repeat it.

 

 

(3) Writing optimization

 

Many writing optimizations can improve code robustness. Here are two points.

 

  • Switches need default to handle exceptions or defaults.

 

  • Make a judgment before accessing an object or array

 

For example, A.B.C is changed to a & & A.B & & a.b.c. If TypeScript is used, it can be written as follows: a b?. c.

 

 

(4) Third party library selection

 

Using the third library can reduce the number of wheels and improve the development efficiency. However, if the third-party package is not robust, the functions using the third-party package will not be robust.

 

Robust third-party libraries are mature and stable. It is best not to select a third-party library in the following cases:

 

  • Just came out.

 

  • There's no stable version yet. If the library follows the semantic version specification, none of the libraries with a major version number of 0 is a stable version.

 

  • Few users. The number of downloads is small and the number of star s is low.

 

  • There is no code to test.