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.