Home > Web Front-end > JS Tutorial > body text

Explanation of JavaScript exception handling

一个新手
Release: 2017-10-25 14:49:33
Original
1436 people have browsed it

When the JavaScript engine executes JavaScript code, various exceptions may occur, such as syntax exceptions, missing features in the language, due to abnormal output from the server or user resulting in anomalies.

The Javascript engine is single-threaded, so once an exception is encountered, the Javascript engine usually stops execution, blocks subsequent code and throws an exception message, so For foreseeable exceptions, we should catch and correctly display them to users or developers.

Error object

throw and Promise.reject() can throw string type exceptions, and can throw a Error Exception of object type.

A Error object type exception not only contains an exception information, but also contains a traceback stack so that you can easily find the number of lines of code where the error occurs through the traceback stack.

So it is recommended to throw Error object type exceptions instead of string type exceptions.

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 after login

Throw custom exception types in code and catch them

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

Throw

throw expression;
Copy after login
Copy after login

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

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 error
Copy after login

Try / Catch

try {
   try_statements
}
[catch (exception) {
   catch_statements
}]
[finally {
   finally_statements
}]
Copy after login

try/catch is mainly used to catch exceptions. The try/catch statement contains a try block, and at least one catch block or a finally block. The following are three forms Statement of try:

  • try...catch

  • try...finally

  • try...catch...finally

try Put statements or functions that may generate exceptions in the block

# The

##catch block contains the statement to be executed. When an exception is thrown in the try block, the catch block will capture the exception information and execute# Code in the ##catch block, if no exception is thrown in the try block, this catch block will be skipped. The

finally

block is executed after the try block and the catch block. It is always executed regardless of whether an exception is thrown or caught. When exception information is thrown in the finally block, the exception information in the try block will be overwritten.

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 it2
Copy after login
If a value is returned from the

finally

block, then this value will become the return value of the entire try-catch-finally, regardless of whether there is a The return statements are in try and catch. This includes exceptions thrown within catch blocks.

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()); // 3
Copy after login
Try / Catch Performance

A well-known anti-optimization mode is to use

try/catch

. The

try/catch

statement used in the V8 (the same situation may occur in other JS engines) function cannot be optimized by the V8 compiler. Refer to http://www.html5rocks.com/en/tutorials/speed/v8/window.onerror

by defining an event listener on

window.onerror

function, uncaught exceptions generated by other codes in the program are often captured by the listening function registered above window.onerror. And at the same time capture some information about the exception.

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

  • message

    :Exception message (string)

  • source

    :Exception occurred Script URL (string)

  • lineno

    : The line number where the exception occurred (number)

  • colno

    : The column number (number) where the exception occurred

  • error

    : Error object (object)

  • Note : Safari and IE10 do not yet support the use of the fifth parameter in the callback function of
window.onerror

, which is an Error object with a traceback stack

try/catch

cannot catch exceptions in asynchronous code, but it will throw the exception globally and window.onerror can catch it.

try {
    setTimeout(() => {
        throw new Error("some message");
    }, 0);
} catch (err) {
    console.log(err);
}
// Uncaught Error: some message
Copy after login
window.onerror = (msg, url, line, col, err) => {
    console.log(err);
}
setTimeout(() => {
    throw new Error("some message");
}, 0);
// Error: some message
Copy after login
In Chrome,

window.onerror

can detect exceptions in script files referenced from other domains and mark these exceptions as Script error. If you don't want to process these script files imported from other domains, you can filter them out through the Script error tag in the program. However, in Firefox, Safari or IE11, cross-domain JS exceptions will not be introduced. Even in Chrome, if you use try/catch to surround these nasty codes, Chrome will no longer detect it. to these cross-domain exceptions.

在Chrome中,如果你想通过 window.onerror 来获取到完整的跨域异常信息,那么这些跨域资源必须提供合适的跨域头信息。

Promise中的异常

Promise中抛出异常

new Promise((resolve,reject)=>{
    reject();
})
Copy after login
Promise.resolve().then((resolve,reject)=>{
    reject();
});
Copy after login
Promise.reject();
Copy after login
throw expression;
Copy after login
Copy after login

Promise中捕捉异常

promiseObj.then(undefined, (err)=>{
    catch_statements
});
Copy after login
promiseObj.catch((exception)=>{
    catch_statements
})
Copy after login

JavaScript 函数中,只有 return / yield / throw 会中断函数的执行,其他的都无法阻止其运行到结束的。

resolve / reject 之前加上 return 能阻止往下继续运行。

without return

Promise.resolve()
.then(() => {
    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 reject
Copy after login

use return

Promise.resolve()
.then(() => {
    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 error
Copy after login

Throw or Reject

无论是 try/catch 还是 promise 都能捕获到的是“同步”异常

reject 是回调,而 throw 只是一个同步的语句,如果在另一个异步的上下文中抛出,在当前上下文中是无法捕获到的。

因此在 Promise 中使用 reject 抛出异常。否则 catch 有可能会捕捉不到。

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

// Uncaught Error: throw error
Copy after login
Promise.resolve()
.then(() => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error('throw error'));
        }, 0);
    });
})
.catch((err) => {
    console.log(err);
});

// Error: throw error
Copy after login

window.onunhandledrejection

window.onunhandledrejectionwindow.onerror 类似,在一个JavaScript Promise 被 reject 但是没有 catch 来捕捉这个 reject时触发。并且同时捕获到一些关于异常的信息。

window.onunhandledrejection = event => { 
    console.log(event.reason);
}
Copy after login

event事件是 PromiseRejectionEvent 的实例,它有两个属性:

  • event.promise:被 rejected 的 JavaScript Promise

  • event.reason:一个值或 Object 表明为什么 promise 被 rejected,是 Promise.reject() 中的内容。

window.rejectionhandled

因为 Promise 可以延后调用 catch 方法,若在抛出 reject 时未调用 catch 进行捕捉,但稍后再次调用 catch,此时会触发 rejectionhandled 事件。

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

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

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

// Uncaught (in promise) Error: throw error
// 1秒后输出
// Error: throw error
// rejection handled
Copy after login

统一异常处理

代码中抛出的异常,一种是要展示给用户,一种是展示给开发者。

对于展示给用户的异常,一般使用 alerttoast 展示;对于展示给开发者的异常,一般输出到控制台。

在一个函数或一个代码块中可以把抛出的异常统一捕捉起来,按照不同的异常类型以不同的方式展示,对于。

需要点击确认的异常类型:
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 after login

弹窗提示的异常类型:
toastError.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 after login

提示开发者的异常类型:
devError.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 after login

异常处理器:
抛出普通异常时,可以带上 stackoverflow 上问题的列表,方便开发者查找原因。
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=${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 after login


The above is the detailed content of Explanation of JavaScript exception handling. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!