What exceptions and common errors cannot be caught by try-catch in the front end

During development, our goal is to 0error,0warning.

But there are many factors that are beyond our control. In order to avoid errors in a certain piece of code and affect the operation of other modules or the overall code, we often use modules try-catchto actively catch some exceptions or errors.

For example, after we get the parameters urlin and JSONparse them, we need to try-catchwrap them here, because we cannot guarantee that the parameters we get can be parsed normally:

const user= getQueryString('user');
if (user) {
    
    
  try {
    
    
    const {
    
     id, username} = JSON.parse(user);
    console.log(id, username);
  } catch (err) {
    
    
    console.error(err);
  }
}

In the process of copying the link, the user may intentionally or unintentionally copy incompletely, resulting in incomplete parameters, which JSON.parsecannot be parsed json string. To avoid JSONparsing , we can try-catchinclude it with .

1. What errors cannot be caught by try-catch

We often use try-catchmodules to actively catch some exceptions or errors, so as to prevent the code of this block from affecting the operation of other modules or the overall code. But in some cases, try-catchexceptions in the code cannot be caught!

1. Cross domain error

When we use the xhr request interface, if the interface does not support cross-domain, the browser will prompt an error in the console:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>trycatch演示</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"></script>
</head>

<body>
    <button onclick="cli()">点我</button>
    <script>
        function cli() {
    
    
            try {
    
    
                $.get('http://www.baidu.com', function success(data) {
    
    
                    console.log(data)
                })
            } catch (e) {
    
    
                console.log(e)
            }
        }
    </script>
</body>

</html>
Access to XMLHttpRequest at 'https://www.baidu.com/' (redirected from 'http://www.baidu.com/') from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

From the picture, we can see that a cross-domain error occurred when requesting the interface, but it did not enter the catch. Through the monitoring of xhr.onerror, we can know that the xhr request has generated a request error.
insert image description here

2. Asynchronous errors

If an asynchronous module tryin , generates an error, catchit cannot be caught, for example:

// setTimeout中的错误
try {
    
    
  setTimeout(function () {
    
    
    throw new Error('error in setTimeout'); // 200ms后会把异常抛出到全局
  }, 200);
} catch (err) {
    
    
  console.error('catch error', err); // 不会执行
}

insert image description here

// Promise中的错误
try {
    
    
 Promise.resolve().then(() => {
    
    
   throw new Error('error in Promise.then');
 });
} catch (err) {
    
    
 console.error('catch error', err);

insert image description here
As can be seen from the running results, neither of these two codes enters catchthe module .

Why didn't it enter the catch module?
When an asynchronous function throws an exception, for a macro task, the function has been pushed onto the stack when the function is executed, and it is not on the stack where the try-catch is located at this time, so the try-catch cannot catch the error. For microtasks, such as promise, the exception of the promise's constructor can only be caught by the built-in reject, that is, the .catch function.

The answer to catching asynchronous errors
is to try-catchput inside the asynchronous code.

1. Put try-catch inside setTimeout

// 将try-catch放到setTimeout内部
setTimeout(() => {
    
    
  try {
    
    
    throw new Error('error in setTimeout');
  } catch (err) {
    
    
    console.error('catch error', err);
  }
}, 200);

insert image description here
2. Put try-catch inside then

// 将try-catch放到then内部
Promise.resolve().then(() => {
    
    
  try {
    
    
    throw new Error('error in Promise.then');
  } catch (err) {
    
    
    console.error('catch error', err);
  }
});

insert image description here

3. Use the catch that comes with Promse to catch exceptions

// 使用Promse自带的catch捕获异常
Promise.resolve()
 .then(() => {
    
    
   throw new Error('error in Promise.then');
 })
 .catch((err) => {
    
    
   console.error('Promise.catch error', err);
});

insert image description here
PromiseA great advantage is that it has its own exception capture method catch(), then()which will automatically enter catch()the method when an error occurs in the method and the code cannot run. Therefore, it is recommended to write Promisewhen catch(), otherwise uncaught exceptions will bubble up to the global.

3. How to catch the exception of async-await

awaitCan be .catch()used simultaneously with . try/catchCan catch all exceptions, only errors .catchin asynchronous methodsreject

In other words, if you only want to capture rejecterrors in asynchronous methods, you can capture them awaitwhile using them ..catch()But exceptions other than reject cannot be caught.

As shown below:

1. At the same time, the exception was caught by using reject:

const foo=()=>{
    
    
                return new Promise((resolve, reject) => {
    
    
                    throw new Error('throw 错误')
                });
            }
await foo().catch(e=>{
    
    console.log('捕获到了:'+e)});

insert image description here

2. rejectIf the exception cannot be caught, report an error directly:
(In this case, you need to use try/catch to capture and process)

 const foo=()=>{
    
    
                throw new Error('throw 错误');
                return new Promise((resolve, reject) => {
    
    
                    resolve('resolve 错误')
                });
            }
await foo().catch(e=>{
    
    console.log('捕获到了:'+e)});

insert image description here
But after this kind of exception is caught, catch()the method cannot catch the exception, and it will no longer continue to bubble to the outer layer. The correct approach is that errors generated by the underlying modules should be thrown directly to the business layer, allowing the business layer to decide how to deal with the error instead of swallowing it directly.

4. Multi-layer try-catch

try-catchWhen there are multiple layers , it will catch()be captured by the innermost method, and then it will no longer bubble to the outer layer:

try {
    
    
  try {
    
    
    throw new Error('error');
  } catch (err) {
    
    
    console.error('内层的catch', err); // 内层的catch Error: error
  }
} catch (err) {
    
    
  console.error('最外层的catch', error);
}

insert image description here

The type of error that occurs in js.

Before knowing how to use it try-catch, let's first understand what are the native error types jsin .

jsThere are 6 types of errors that may occur when the code is running:

  1. syntax error( SyntaxError);
  2. typeError( TypeError);
  3. RangeError( RangeError);
  4. evalerror( EvalError);
  5. referenceError( ReferenceError);
  6. URIerror( URIError);

These error types are all inherited from the Errorclass.

1. Syntax error ( SyntaxError)

Grammatical errors are usually caused by developers writing code statements during the development process, which cannot be parsed by the browser:

const a=;

Error message:

VM202:1 Uncaught SyntaxError: Unexpected token ';'

2. Type error ( TypeError);

Type errors usually appear in two situations:

  • The operator is used on an inappropriate type variable, such as using concatthe operator ;
  • The variable of the operation encountered an unexpected nullor undefinedvalue:
const obj = {
    
    };
obj.concat([1]);

error message

VM211:2 Uncaught TypeError: obj.concat is not a function
    at <anonymous>:2:5

insert image description here

const a = null;
a.nickname; //VM218:2 Uncaught TypeError: Cannot read properties of null (reading 'nickname')at <anonymous>:2:3

When writing some methods for other modules to call, when checking that the parameter input is empty or nullempty , TypeErroran error can be thrown.

3. Range error ( RangeError);

This error is usually because the parameters passed in are beyond the specified range. For example, toFixed()the method can accept values ​​within 0-100the range , and when this range is exceeded, this error will be thrown.

Math.PI.toFixed(105); // Uncaught RangeError: toFixed() digits argument must be between 0 and 100

insert image description here

4. evalError ( EvalError);

This kind of error is generally rarely encountered, because when using evalthe operation , even improper errors will throw other types of errors.

new eval(); // Uncaught TypeError: eval is not a constructor
eval = 1234; // 正确执行

insert image description here

5. Reference error ( ReferenceError);

A reference error means that the master and apprentice are accessing an undeclared variable:

console.log(nick); // Uncaught ReferenceError: nick is not defined

insert image description here

6. URIError ( URIError);

This error is usually an error thrown by some operation uri functions, mainly including: encodeURI(), decodeURI(), encodeURIComponent(), decodeURIComponent(), escape(), unescape().

decodeURIComponent('%'); // Uncaught URIError: URI malformed
decodeURIComponent('%23'); // # 正确执行

insert image description here

insert image description here

custom error type

For a slightly larger module, we want to customize some error types. Through these error types, we can see that an error is thrown by a certain module. How should I write it?

Our custom error type should also be inherited from the class Error, which is very simple to implement:

class FingerError extends Error {
    
    
  constructor(message) {
    
    
    super(message);
    this.name = 'FingerError'; // 该错误的名称
    Error.captureStackTrace(this, this.constructor); // 获取错误堆栈的信息
  }
}
 
const err = new FingerError('get name error');
console.error(err); // FingerError: get name error
err instanceof FingerError; // true

insert image description here

Summarize

There are still many ways to generate errors in the front end, and we should pay attention to avoiding these errors at ordinary times. Next, we can also analyze from the perspective of error monitoring, how to monitor the errors and error types that appear on the page.

Guess you like

Origin blog.csdn.net/qq_44732146/article/details/129962657