Recently node write more, background application you know, an exception is not handled well, minutes crash for you to see. In the development process summed up some experience, share to everyone

The Error class

Error class is JS native class, in daily development is also very common, also very simple, I went to MDN before writing the document to check the information:

The Error class is very simple to use, either as new or as function, and then throw it wherever you think you need to throw an exception.

There are several built-in Error types in JS, such as the most common ReferrenceError, which inherit from Error, so we can also define our own Error types, just need to inherit Error, directly on the kernel of MDN:

class CustomError extends Error {
  constructor(foo = 'bar', ... params) {// Pass remaining arguments (including vendor specific ones) to parent constructor
    super(... params);// Maintains proper stack trace for where our error was thrown (only available on V8)
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, CustomError);
    }

    // Custom debugging information
    this.foo = foo;
    this.date = new Date();
  }
}

try {
  throw new CustomError('baz'.'bazMessage');
} catch(e){
  console.log(e.foo); //baz
  console.log(e.message); //bazMessage
  console.log(e.stack); //stacktrace
}
Copy the code

How to catch exceptions

try… Without further ado about catch, we need to mention the catching of promises and await

We usually add a. Catch at the end of a Promise to handle any possible exceptions in the whole Promise execution link, such as:

Promise.resolve()
	.then((a)= > {
		console.log(a); // There is an exception
	})
	.then((a)= > {
		console.log('hi'); // There is no execution here
	})
	.catch(err= > {
		console.log(err); // ReferenceError
	});
Copy the code

Await syntax returns a Promise object as well, but you can try… Catch syntax to catch exceptions

async function sayHi() {
	try {
		let ret = await anotherPromiseFunction();
	}
	catch (err) {
		console.log(err); // The exception thrown by anotherPromiseFunction is handled here}}Copy the code

How to gracefully throw an exception

  1. You need aCustom error classes. JSnativeCan only define basic language exceptions, but we need to frequently define and throw some business-related exceptions in business code, such as:

An API for validating a verification code that throws an exception if the verification code is not in the correct format. This exception should be validating and the caller can clearly interpret and act on the error message.

My custom error class:

/** * @file Error type summary * @author arlenyang */
class ApiError extends Error {
    /** * @constructor * @param {string} code Error code * @param {string} MSG Chinese description */
    constructor(code, msg) {
        super(msg);

        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, CustomError);
        }

        this.code = code;
        this.msg = msg;
    }

    toString() {
        return `ApiThe ${this.stack}\n    The ${this.msg}, errCode: The ${this.code}`; }}// Error type
ApiError.MYSQL_QUERY_ERROR = 1;
ApiError.MYSQL_QUERY_ERROR_DESC = 'Query data failed';

/ /...

Copy the code

The constructor takes two arguments, code and message.

  • Code is the error code, which defines an exception short for the caller to determine the type of error and thus handle the error. This isnodeIn the common
  • Message is a description of the Error, which is supported by the native Error constructor itself

In this class, I store all the error codes and their description fields as static variables, which can also be stored in a separate file for static variables

You can also extend your exception class to do more related things, such as logging errors, reporting, or writing to local logs.

Alternatively, you can customize the output of the exception by overriding the toString method. Remember the error. Stack and error. CaptureStackTrace mentioned earlier? You can optimize the output format of the exception in the toString method, add extra information, and so on

  1. Do not overhandle exceptions. If we wrote every API or function to consider all possible exceptions, we would be dead. We would need to determine which exceptions can be thrown at the caller. These exceptions are usually foreseeable during the execution of the function.checked exception). And other exceptions, may be our code itself has a bug, may also be the error generated by the system call, such exceptions need to consider their own

For example, write an API that reads the contents of a file.

/** * read file * @param {String} filepath filepath * @return {Buffer} file content */
async function readFile(filepath) {}Copy the code

Several exceptions can be expected based on the behavior of this API:

  • The input parameter (Filepath) is empty
  • The file path does not exist
  • Check whether the file corresponding to the file path is a file type

Exceptions to the API that calls the system to read files, filepath that does not conform to the filepath format, and so on, are not the scope of the API. The implementation is as follows:

/** * read file * @param {String} filepath filepath * @return {Buffer} file content */
async function readFile(filepath) {
	// Check whether filepath is empty
	if(! filepath) {// Use custom error classes
		throw new ApiError(
			ApiError.PARAMETER_FORMAT_ERROR,
			ApiError.PARAMETER_FORMAT_ERROR_DESC,
		);
	}
	
	try {
		let stat = await fs.stat(filepath);		
		// Check whether the corresponding file is a file type
		if(! stat.isFile()) {throw new ApiError(
				ApiError.FILE_FORMAT_ERROR,
				ApiError.FILE_FORMAT_ERROR_DESC,
			);
		}
		let content = await fs.readFile(filepath);

		return content;
	}
	catch (err) {
		// Check whether the file exists
		if (err.code === 'ENOENT') {
			throw new ApiError(
				ApiError.FILE_NOT_FOUND_ERROR,
				ApiError.FILE_NOT_FOUND_ERROR_DESC,
			);
		}

		throwerr; }}Copy the code
  1. For promise exception handling, don’t use.catch for all functions’ just to be safe, ‘as this may result in exceptions being swallowed and not being found

    1. For promises that require a catch, try to handle the exception first, and throw back those that can’t

    2. Throw Error instead of promise.reject (error) is more elegant

    3. The difference between a promise’s then(resolve, reject) and then(resolve, null).catch()

    4. Promise. If there is no reject or throw in a catch, then the logic goes to resolve instead of reject

      Promise.resolve()
      	.then((a)= > {
      		console.log(a); // This line will be caught by a catch
      	})
      	.catch(err= > {
      		console.log(err);
      		return 1;
      	})
      	.then(ret= > {
      		console.log(ret); // Will execute and print 1
      	});
      Copy the code

REFERENCE

  1. Advanced Java exception
  2. Correct posture for handling JavaScript exceptions
  3. Error