preface

On the front end, catching and locating exceptions is critical both in development and production.

During the development phase, through detailed error information, we can quickly locate and solve problems. In production, through abnormal monitoring and abnormal buried point information, we can know the abnormal information in the first time, so as not to cause serious consequences.

window.onerror

Global listening exception to catch

When JavaScript runtime errors (including syntax errors) occur, the window raises an error event from the ErrorEvent interface and executes window.onerror(). Loading a global error event handler can be used to automatically collect error reports.

Grammar:

window.onerror = function(message, source, lineno, colno, error) { ... }
Copy the code

Parameter Description:

  • message: Error message (string). Can be used for HTMLonerror=""In the handlerevent.
  • source: script URL (string) where the error occurred
  • lineno: Line number (digit) where the error occurred
  • colno: Column number (digit) where the error occurred
  • error: the Error object

If this function returns true, it prevents execution of the default event handler, that is, no errors are printed on the console.

Okay, so let’s go through an example

Go straight to code

<html>
  <head>
    <script type="text/javascript">
      onerror = handleErr;
      var txt = "";
      function handleErr(msg, source, lineno, colno, error) {
        txt = "There was an error on this page.\n\n";
        txt += Error message: + msg + "\n";
        txt += "Error script URL:" + source + "\n";
        txt += "Error number of rows:" + lineno + "\n\n";
        txt += "Number of columns in error:" + colno + "\n\n";
        txt += "Click OK to continue.\n\n";
        alert(txt);
        return false;
      }
      function message() {
        adddlert("Welcome guest!");
      }
    </script>
  </head>

  <body>
    <input type="button" value="View message" onclick="message()" />
  </body>
</html>
Copy the code

When you click on View Message, the following popup will appear

Also, the console will get an error, and this is our last return false. Return true does not see the error message

In the onError callback function, we send relevant buried information (relevant error message, number of rows, number of columns, etc.) to our monitoring platform to implement basic page monitoring

try… catch…

try… catch… . Where try specifies the block to run and catch specifies the response to be thrown when the block runs in error.

Such as:

try {
  nonExistentFunction();
}
catch(error) {
  console.error(error);
  // expected output: ReferenceError: nonExistentFunction is not defined
  // Note - error messages will vary depending on browser
}
Copy the code

We use try… catch… The most important is not because of one error, resulting in our page hanging. In catch we can also send relevant buried points to our monitoring platform.

About Vue exception catching

This scenario exists because Vue itself has passed the try… catch… The window.onerror event is not raised, so we sometimes need to do exception catching specifically for Vue

We can use vue.config. errorHandler to catch exceptions globally for Vue

Specifies a handler that does not catch errors during rendering and viewing of the component. When this handler is called, it gets an error message and a Vue instance. In addition to sending a buried message, we can print an error message in the console. Note that this method is not printed in the console by default, which is not friendly to our development

Vue.config.errorHandler = function(err, vm, info) {// Handle error // 'info' is Vue specific error information, such as the lifecycle hook where the error occurred // only available in 2.2.0+}Copy the code

About the cross domain

When errors occur when loading scripts from different domains, to avoid information leakage, syntax details are not reported, but simply “Script error”.

The solution is to solve this problem by using the Crossorigin attribute in the script tag and requiring the server to send the appropriate CORS HTTP response header, i.e. requiring the server to set access-Control-Allow-Origin

<script src="http://cdn.xxx.com/index.js" crossorigin="anonymous"></script>
Copy the code

In webpack, we can set crossOriginLoading in output to anonymous, as shown below

output: {
    path: path.resolve(__dirname, '.. /dist'),
    filename: '[name].js',
    publicPath: ' ',
    chunkFilename: '[name].js',
    library: 'MST',
    crossOriginLoading: 'anonymous'
  }
Copy the code

About sourcemap

When we used Webpack to package our Vue applications, the resulting code was mixed up for both security and performance reasons. But in our development stage, this is not conducive to our location and debugging problems. So we can turn on source Map mode. We just need to configure the Webpack devtool option, see webpack Devtool website. As shown in the example:

devtool: 'eval-source-map'
Copy the code

But sourcemap works well, but we generally can’t use it in production, mainly for security reasons. If you put sourcemap files online, you may risk code leakage, business loss, system attack, etc. So the online question, how can we know the detailed exception information?

First, the local Webpack package still generates the Sourcemap file, but we don’t upload it to the server, just keep it on the local server. When an error is reported, we replace it with our local Sourcemap file using whistle interceptor and js online. This is equivalent to loading our local sourmap file.

Exception catching for asynchrony

Why try… catch… Can’t catch an asynchronous exception?

First of all, js is single threaded. When the code in the try is asynchronous, when the asynchronous execution fails, the synchronous code may have been removed from the execution stack and finished executing, so there is no way to catch the asynchronous exception

So how do we catch asynchronous exceptions?

  • Exceptions can be caught through the Promise catch
// reject
const p1 = new Promise((reslove, reject) => {
  if(1) { reject(); }}); p1.catch((e) => console.log('p1 error'));
Copy the code
// throw new Error
const p2 = new Promise((reslove, reject) => {
  if(1) {
    throw new Error('p2 error')}}); p2.catch((e) => console.log('p2 error'));
Copy the code

A Promise can be caught by a catch, whether it is a reject or a throw new Error inside

  • Catch exceptions with async and await
run();
async function run() {
    try {
        await Promise.reject(new Error("Oops!"));
    } catch (error) {
        error.message; // "Oops!"}}Copy the code

reference

GlobalEventHandlers.onerror

JS intercepts/catches global errors global Error onError

Webpack what you don’t know about sourceMap

JS asynchronous errors catch two or three things

Welcome to my grocery store, don’t buy anything, we just have a chat, talk about heart ~