>  기사  >  웹 프론트엔드  >  JavaScript 예외 처리 설명

JavaScript 예외 처리 설명

一个新手
一个新手원래의
2017-10-25 14:49:331490검색

JavaScript 엔진이 JavaScript 코드를 실행할 때 구문 예외, 언어 기능 누락, 서버 또는 사용자의 비정상적인 출력으로 인한 예외 등 다양한 예외가 발생할 수 있습니다.

그리고 Javascript 엔진은 단일 스레드이므로 일단 예외가 발생하면 Javascript 엔진은 일반적으로 실행을 중지하고 후속 코드를 차단하고 예외 메시지를 던집니다. 따라서 예측 가능한 예외의 경우 이를 포착하여 올바르게 표시해야 합니다. 사용자나 개발자에게.

Error object

throwPromise.reject()는 문자열 유형 예외를 발생시킬 수 있고 Error 객체 유형 예외를 발생시킬 수 있습니다.

A Error 객체형 예외에는 예외 정보뿐 아니라 트레이스백 스택도 포함되어 있어 트레이스백 스택을 통해 오류가 발생한 코드 라인 수를 쉽게 찾을 수 있습니다.

그래서 문자열 유형 예외 대신 Error 객체 유형 예외를 발생시키는 것이 좋습니다.

나만의 예외 생성자 만들기

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;

코드에 사용자 정의 예외 유형을 던지고

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

Throw

throw expression;

throw 문을 잡아 사용자 정의 예외를 던집니다. 현재 함수의 실행이 중지되고(throw 이후의 문은 실행되지 않음) 제어가 호출 스택의 첫 번째 catch 블록으로 전달됩니다. 호출자 함수에 catch 블록이 없으면 프로그램이 종료됩니다.

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

Try/Catch

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

try/catch는 주로 예외를 잡는 데 사용됩니다. try/catch 문에는 try 블록과 하나 이상의 catch 블록 또는 finally 블록이 포함됩니다. 다음은 try 문의 세 가지 형식입니다.

  • try...catch

  • try...finally

  • try...catch...finally

try 예외를 생성할 수 있는 문이나 함수는 블록에 배치됩니다.

catch 블록에는 다음이 포함됩니다. 실행할 명령문, try 블록에서 예외가 발생하면 catch 블록은 예외 정보를 캡처하고 try에서 예외가 발생하지 않으면 catch 블록의 코드를 실행합니다. 블록, 이 catch 블록을 건너뜁니다.

finally 블록은 try 블록과 catch 블록 다음에 실행됩니다. 예외가 발생하거나 포착되는지 여부에 관계없이 항상 실행됩니다. finally 블록에 예외 정보가 발생하면 try 블록의 예외 정보를 덮어쓰게 됩니다.

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

값이 finally 블록에서 반환되면 이 값은 tryreturn 문이 있는지 여부에 관계없이 전체 try-catch-finally의 반환 값이 됩니다. 잡아. 여기에는 catch 블록 내부에 발생한 예외가 포함됩니다.

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

Try/Catch Performance

try/catch를 사용하는 잘 알려진 최적화 방지 패턴이 있습니다.

V8에서 사용되는 try/catch 문(다른 JS 엔진에서도 동일한 상황이 발생할 수 있음) 함수는 V8 컴파일러에서 최적화할 수 없습니다. http://www.html5rocks.com/en/tutorials/speed/v8/

window.onerror

를 참고하세요. window.onerror에 이벤트 리스닝 함수를 정의하면 프로그램의 다른 코드에서 발생하는 잡히지 않는 오류 예외 window.onerror 위에 등록된 듣기 기능에 의해 종종 포착됩니다. 동시에 예외에 대한 일부 정보를 캡처합니다.

window.onerror = function (message, source, lineno, colno, error) { }
  • message: 예외 정보(문자열) message:异常信息(字符串)

  • source:发生异常的脚本URL(字符串)

  • lineno:发生异常的行号(数字)

  • colno:发生异常的列号(数字)

  • error:Error对象(对象)

注意:Safari 和 IE10 还不支持在 window.onerror 的回调函数中使用第五个参数,也就是一个 Error 对象并带有一个追溯栈

try/catch 不能够捕获异步代码中的异常,但是其将会把异常抛向全局然后 window.onerror 可以将其捕获。

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

在Chrome中,window.onerror 能够检测到从别的域引用的script文件中的异常,并且将这些异常标记为Script error。如果你不想处理这些从别的域引入的script文件,那么可以在程序中通过Script error

source: 예외가 발생한 스크립트 URL(문자열) 🎜🎜🎜🎜lineno : 예외가 발생한 줄 번호(번호) 🎜🎜🎜🎜<code>colno: 예외가 발생한 열 번호(번호) 🎜🎜🎜🎜error: 오류 개체( 개체)🎜🎜🎜🎜참고: Safari 및 IE10은 아직 🎜window.onerror🎜의 콜백 함수에서 다섯 번째 매개 변수 사용을 지원하지 않습니다. 이는 추적 스택이 있는 🎜Error🎜 개체🎜🎜🎜try입니다. /catch🎜 비동기 코드의 예외는 포착할 수 없지만 전역적으로 예외를 발생시키고 🎜window.onerror🎜가 이를 포착할 수 있습니다. 🎜
new Promise((resolve,reject)=>{
    reject();
})
Promise.resolve().then((resolve,reject)=>{
    reject();
});
🎜Chrome에서 🎜window.onerror🎜는 다른 도메인에서 참조된 스크립트 파일의 예외를 감지하고 이러한 예외를 스크립트 오류로 표시할 수 있습니다. 다른 도메인에서 가져온 이러한 스크립트 파일을 처리하지 않으려면 프로그램의 스크립트 오류 태그를 통해 필터링할 수 있습니다. 그러나 Firefox, Safari 또는 IE11에서는 도메인 간 JS 예외가 도입되지 않습니다. Chrome에서도 🎜try/catch🎜를 사용하여 이러한 불쾌한 코드를 둘러싸면 Chrome은 더 이상 이러한 크로스 도메인 JS 예외를 감지하지 않습니다. 🎜

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

Promise中的异常

Promise中抛出异常

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

Promise中捕捉异常

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

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

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

without return

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

// before excute reject
// throw error
// after excute reject

use return

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

// before excute reject
// throw error

Throw or Reject

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

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

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

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

// Uncaught Error: throw error
Promise.resolve()
.then(() => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error(&#39;throw error&#39;));
        }, 0);
    });
})
.catch((err) => {
    console.log(err);
});

// Error: throw error

window.onunhandledrejection

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

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

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(&#39;rejection handled&#39;);
}

let p = Promise.reject(new Error(&#39;throw error&#39;));

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

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

统一异常处理

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

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

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

需要点击确认的异常类型:
ensureError.js

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

export default EnsureError;

弹窗提示的异常类型:
toastError.js

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

export default ToastError;

提示开发者的异常类型:
devError.js

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

export default DevError;

异常处理器:
抛出普通异常时,可以带上 stackoverflow 上问题的列表,方便开发者查找原因。
errorHandler.js

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

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;


위 내용은 JavaScript 예외 처리 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.