When a JavaScript engine executes JavaScript code, various exceptions can occur, such as syntax exceptions, missing functionality in the language, and exceptions due to abnormal output from the server or the user.

Javascript engines are single-threaded, so when an exception is encountered, the Javascript engine usually stops execution, blocks subsequent code and throws an exception message, so predictable exceptions should be caught and properly displayed to the user or developer.

The Error object

Throw and promise.reject () can throw an exception of type string, and can throw an exception of type Error object.

An exception of type Error contains not only an exception message, but also a trace stack so that you can easily find the number of lines of code that went wrong.

Therefore, it is recommended to throw an exception of the Error object type rather than a string type.

Create your own exception constructor



function MyError(message) {
    var instance = new Error(message);
    instance.name = 'MyError';
    Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
    return instance;
}

MyError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: MyError,
        enumerable: false,
        writable: true,
        configurable: true}});if (Object.setPrototypeOf) {
    Object.setPrototypeOf(MyError, Error);
} else {
    MyError.__proto__ = Error;
}

export default MyError;Copy the code

Throw custom exception types in your code and catch them



try {
    throw new MyError("some message");
} catch(e){
    console.log(e.name + ":" + e.message);
}Copy the code

Throw



throw expression; Copy the code

The throw statement is used to throw a user-defined exception. Execution of the current function is stopped (statements after the throw will not execute), and control is passed to the first catch block in the call stack. If there is no catch block in the caller function, the program terminates.



try {
    console.log('before throw error');
    throw new Error('throw error');
    console.log('after throw error');
} catch (err) {
    console.log(err.message);
}

// before throw error
// throw errorCopy the code

Try / Catch



try {
   try_statements
}
[catch (exception) {
   catch_statements
}]
[finally {
   finally_statements
}]Copy the code

Try /catch is used to catch exceptions. A try/catch statement contains a try block and at least one catch block or finally block. There are three forms of try declarations:

  • try… catch
  • try… finally
  • try… catch… finally

The try block contains statements or functions that may raise exceptions

A catch block contains the statement to be executed. When an exception is thrown in a try block, the catch block catches the exception and executes the code in the catch block. If no exception is thrown in a try block, the catch block will skip.

A finally block executes after a try block and a catch block. It always executes whether or not an exception is thrown or caught. When an exception is thrown ina finally block, it overwrites the exception ina try block.



try {
    try {
        throw new Error('can not find it1');
    } finally {
        throw new Error('can not find it2'); }}catch (err) {
    console.log(err.message);
}

// can not find it2Copy the code

If a value is returned from a finally block, that value will be the return value of the entire try-catch-finally, regardless of whether there are any return statements in the try and catch. This includes exceptions thrown in the catch block.



function test() {
    try {
        throw new Error('can not find it1');
        return 1;
    } catch (err) {
        throw new Error('can not find it2');
        return 2;
    } finally {
        return 3; }}console.log(test()); / / 3Copy the code

Try/Catch performance

A well-known anti-optimization pattern is to use try/catch.

Use of try/catch statements in V8 (and possibly other JS engines) functions cannot be optimized by the V8 compiler. Refer to www.html5rocks.com/en/tutorial…

window.onerror

By defining an event listener on window.onerror, uncaught exceptions generated by other code in the program are often caught by listeners registered on window.onerror. And some information about the exception is caught at the same time.



window.onerror = function (message, source, lineno, colno, error) {}Copy the code
  • message: Exception information (string)
  • source: URL of the script where the exception occurred (string)
  • lineno: Line number (digit) of the exception
  • colno: Column number (digit) of the exception
  • error: Error object (object)

Note: Safari and IE10 do not yet support a fifth argument in the window.onerror callback, which is an Error object with a trace stack

Try /catch cannot catch an exception in asynchronous code, but it will throw the exception globally and then window.onError can catch it.



try {
    setTimeout((a)= > {
        throw new Error("some message");
    }, 0);
} catch (err) {
    console.log(err);
}
// Uncaught Error: some messageCopy the code


window.onerror = (msg, url, line, col, err)= > {
    console.log(err);
}
setTimeout((a)= > {
    throw new Error("some message");
}, 0);
// Error: some messageCopy the code

In Chrome, window.onError can detect exceptions in script files referenced from other fields and mark those exceptions as Script error. If you don’t want to process script files imported from other fields, you can filter them out in your program with the Script Error flag. However, in Firefox, Safari, or Internet Explorer 11, cross-domain JS exceptions are not introduced, and even in Chrome, if you surround the offending code with a try/catch, Chrome no longer detects these cross-domain exceptions.

In Chrome, if you want to get full cross-domain exception information through window.onerror, these cross-domain resources must provide the appropriate cross-domain header information.

Exceptions in promises

The Promise throws an exception



new Promise((resolve,reject)= >{
    reject();
})Copy the code


Promise.resolve().then((resolve,reject)= >{
    reject();
});Copy the code


Promise.reject();Copy the code


throw expression; Copy the code

Catch exceptions in promises



promiseObj.then(undefined.(err)= >{
    catch_statements
});Copy the code


promiseObj.catch((exception)= >{
    catch_statements
})Copy the code

In JavaScript functions, only return/yield/throw interrupts the function’s execution, and nothing else prevents it from running to completion.

A return before resolve/reject prevents further action.

Without return:



Promise.resolve()
.then((a)= > {
    console.log('before excute reject');
    reject(new Error('throw error'));
    console.log('after excute reject'); }).catch((err)= > {
    console.log(err.message);
});

// before excute reject
// throw error
// after excute rejectCopy the code

Use return:



Promise.resolve()
.then((a)= > {
    console.log('before excute reject');
    return reject(new Error('throw error'));
    console.log('after excute reject'); }).catch((err)= > {
    console.log(err.message);
});

// before excute reject
// throw errorCopy the code

Throw or Reject

What either a try/catch or a promise can catch is a “synchronous” exception

Reject is a callback, while throw is just a synchronous statement that cannot be caught in the current context if thrown in another asynchronous context.

So use reject in the Promise to throw an exception. Otherwise the catch may not catch.



Promise.resolve()
.then((a)= > {
    setTimeout((a)= >{
        throw new Error('throw error');
    },0); }).catch((err)= > {
    console.log(err);
});

// Uncaught Error: throw errorCopy the code


Promise.resolve()
.then((a)= > {
    return new Promise((resolve, reject)= > {
        setTimeout((a)= > {
            reject(new Error('throw error'));
        }, 0); }); }).catch((err)= > {
    console.log(err);
});

// Error: throw errorCopy the code

window.onunhandledrejection

Window. Onunhandledrejection with window. Onerror similar, in a JavaScript Promise be reject but didn’t catch to catch this reject trigger. And some information about the exception is caught at the same time.



window.onunhandledrejection = event= > { 
    console.log(event.reason);
}Copy the code

The event event is an instance of the PromiseRejectionEvent, which has two properties:

  • event.promise: Rejected JavaScript Promise
  • event.reason: a value or Object indicates why the promise is rejected, yesPromise.reject()The content of.

window.rejectionhandled

Because a Promise can defer calling a catch method, if catch is not called when reject is thrown but is called again later, the rejectionHandled event is raised.



window.onrejectionhandled = event= >
{
    console.log('rejection handled');
}

let p = Promise.reject(new Error('throw error'));

setTimeout((a)= >{
    p.catch(e= >{console.log(e)});
},1000);

// Uncaught (in promise) Error: throw error
// Output after 1 second
// Error: throw error
// rejection handledCopy the code

Unified Exception Handling

Exceptions thrown in code are either presented to the user or to the developer.

For exceptions displayed to users, alert or toast are generally used. Exceptions shown to developers are generally printed to the console.

Exceptions thrown can be captured in a single function or code block and presented in different ways according to different exception types.

The exception type you need to click to confirm: ensureError.js



function EnsureError(message = 'Default Message') {
    this.name = 'EnsureError';
    this.message = message;
    this.stack = (new Error()).stack;
}
EnsureError.prototype = Object.create(Error.prototype);
EnsureError.prototype.constructor = EnsureError;

export default EnsureError;Copy the code

The exception type that pops up: toasteror.js



function ToastError(message = 'Default Message') {
    this.name = 'ToastError';
    this.message = message;
    this.stack = (new Error()).stack;
}
ToastError.prototype = Object.create(Error.prototype);
ToastError.prototype.constructor = ToastError;

export default ToastError;Copy the code

The exception type that prompts the developer: deveror.js



function DevError(message = 'Default Message') {
    this.name = 'ToastError';
    this.message = message;
    this.stack = (new Error()).stack;
}
DevError.prototype = Object.create(Error.prototype);
DevError.prototype.constructor = DevError;

export default DevError;Copy the code

Exception handler: When you throw a normal exception, you can bring a list of problems on StackOverflow with you to find the cause. errorHandler.js



import EnsureError from './ensureError.js';
import ToastError from './toastError.js';
import DevError from './devError.js';
import EnsurePopup from './ensurePopup.js';
import ToastPopup from './toastPopup.js';

function errorHandler(err) {
    if (err instanceof EnsureError) {
        EnsurePopup(err.message);
    } else if (err instanceof ToastError) {
        ToastPopup(err.message);
    }else if( err instanceof DevError){
        DevError(err.message);
    }else{
        error.message += ` https://stackoverflow.com/questions?q=The ${encodeURI(error.message)}`
        console.error(err.message); }}window.onerror = (msg, url, line, col, err) = > {
    errorHandler(err);
}

window.onunhandledrejection = event= >{
    errorHandler(event.reason);
};

export default errorHandler;Copy the code

Welcome to Leechikit: SegmentFault.com

The end of this article, questions and comments are welcome. Writing original articles is not easy, if this article is helpful to you, please like, recommend and follow the author to support.