JavaScript 예외 처리


82

JavaScript 내에서 발생하는 모든 예외를 포착하는 가장 좋은 기술은 무엇입니까?

분명히 가장 좋은 방법은 try ... catch를 사용하는 것입니다. 그러나 비동기 콜백 등을 사용하면 까다로울 수 있습니다.

IE와 Gecko 브라우저가 window.onerror를 지원한다는 것을 알고 있지만 Opera와 Safari는 어떻습니까?

다음은 중앙 예외 처리 솔루션을 갖고 싶은 테스트 사례입니다.

// ErrorHandler-Test1
var test = null;
test.arg = 5;
// ErrorHandler-Test2
throw (new Error("Hello"));
// ErrorHandler-Test3
throw "Hello again";
// ErrorHandler-Test4
throw {
    myMessage: "stuff",
    customProperty: 5,
    anArray: [1, 2, 3]
};
// ErrorHandler-Test5
try {
    var test2 = null;
    test2.arg = 5;
} catch(e) {
    ErrorHandler.handleError(e);
}
// ErrorHandler-Test6
try {
    throw (new Error("Goodbye"));
} catch(e) {
    ErrorHandler.handleError(e);
}
// ErrorHandler-Test7
try {
    throw "Goodbye again";
} catch(e) {
    ErrorHandler.handleError(e);
}
// ErrorHandler-Test8
try {
    throw {
        myMessage: "stuff",
        customProperty: 5,
        anArray: [1, 2, 3]
    };
} catch(e) {
    ErrorHandler.handleError(e);
}

다른 테스트 사례가 생각되면 언급하십시오. 이러한 경우 중 일부는 ErrorHandler.handleError 메서드를 언급합니다. 이것은 try ... catch를 사용할 때 권장되는 지침 일뿐입니다.


내 대답에 대한 댓글을 눈치 채지 못했다는 것이 분명했기 때문에 "질문에 언급 됨"이라는 질문이 "그러나 Opera와 Safari는 어떻습니까?" 여기에 제기 된 질문에 구체적으로 대답했습니다. WTF?
눈꺼풀 없음

1
WebKit에서 window.onerror누락은 2003 년 부터 문제가되었지만 마침내 해결되는 것처럼 보입니다 . 물론 오페라는 완고 할 것입니다.
josh3736

파이어 폭스 7.0.1 - - 참고 window.onerror에서 잘 작동 IE 8 - 크롬 16 - 오페라 11.60
비탈리 Kaplich

11
이것이 왜 닫혔는지 확실하지 않습니다. 재 개설에 투표했습니다.
ripper234

1
동의합니다. 이것은 유용한 질문입니다. 내가 생각할 수있는 유일한 것은 casperOne이 이것이 일종의 브라우저 전쟁 토론이 될 것이라고 두려워하는 것뿐입니까?
Jordan Reiter

답변:


23

모든 이벤트 처리기를 할당하기 위해 jQuery 와 같은 라이브러리를 사용하는 경우 window.onerrorjQuery 이벤트 처리기 코드와 on ready 함수를 오류 처리 기능과 함께 조합 하여 래핑 할 수 있습니다 (참조 : JavaScript 오류 추적 : window.onerror가 충분하지 않은 이유 ).

  • window.onerror: IE의 모든 오류 (및 Firefox의 대부분의 오류)를 포착하지만 Safari 및 Opera에서는 아무 작업도 수행하지 않습니다.
  • jQuery 이벤트 핸들러 : 모든 브라우저에서 jQuery 이벤트 오류를 ​​포착합니다.
  • jQuery 준비 기능 : 모든 브라우저에서 초기화 오류를 포착합니다.

나는 이미 해결책을 제공하지 않는 기사를 읽었습니다. 나는 jQuery를 사용하지 않지만 당신이 암시하는 것에 대해 걱정합니다. jQuery가 예외를 먹고 있다는 말입니까?! 아니면 단순히 로깅 기능 만 제공합니까 (원래 질문에 답변 한 후에 만 ​​유용함)?
harley.333

jQuery는 예외와 관련하여 특별한 작업을 수행하지 않습니다. 그러나 모든 이벤트를 추가하기 위해 jQuery를 사용하면 내 대답의 두 번째 링크에 설명 된대로 try catch 문과 오류 처리 코드를 추가 할 수있는 단일 위치를 제공합니다.
Karl

2
제공된 링크 이동 : blogs.cozi.com/tech/2008/04/…
natacado

1
여전히 사실입니까? onerrorSafari + Chrome 에서 정상적인 처리 방법을 시도했으며 제대로 작동하는 것 같습니다.
Juri

"충분하지 않은"이유에 대한 링크는 꽤 오래된 정보이며 지금은 그렇지 않습니다.
vsync 2014-06-23

21

WebKit (Safari, Chrome 등)은 이제 onerror.

원본 게시물 : 내가 아는 한 WebKit / Safari는 onerror이벤트를 지원하지 않습니다 . 정말 부끄러운 일입니다.


19
어, 아니에요. 질문 : "하지만 Opera와 Safari는 어떻습니까?"
눈꺼풀 없음

에서와 같이 나는 질문 게시물에 제기 된 질문에 구체적으로 대답했습니다.
눈꺼풀 없음

8
나는 그가 "오페라와 사파리 [윈도우 .onerror가없는]에 대해 [내가 무엇을 할 수 있는가]?"를 의미했다고 생각한다.
nickf

10
@nickf, 아마도,하지만 만약 그렇다면 그것은 매우 나쁘게 표현되었으며, 내 해석은 최악의 이해력과 기껏해야 가장 가능성이 높습니다. 사람들이 내 대답을 투표하는 것이 특히 문제는 주어진, 매우 가난한 이유 없는 상태 를, 그리고 다른 독자는 찬성 또는 반대 성명 혜택을 누릴 수 있습니다.
눈꺼풀 없음

이제 Chrome이 지원하는 것 같습니다.
다니엘 X 무어

7

실제로 jquery 접근 방식은 그렇게 나쁘지 않습니다. 보다:

http://docs.jquery.com/Events/error#fn

과:

$(window).error(function(msg, url, line){
  $.post("js_error_log.php", { msg: msg, url: url, line: line });
});

11
지금 이것을 찾는 사람을 위해-jquery는 실제로 이벤트를 window.error 이벤트에 바인딩하지 않는 것이 좋습니다-위의 문서 링크를 참조하십시오. 추출 : jQuery 오류 이벤트 처리기를 창 개체에 연결하면 안됩니다. [...] 대신 window.onerror를 사용하십시오.
zcrar70 2011 년

ofc 이런 식으로 묶여서는 안되며 비논리적입니다! 이 입찰이 이루어 졌을 때 많은 오류가 발생할 수 있습니다 (성공적으로 이루어진 경우 ...)
vsync

6

자신의 예외 처리기로 모든 예외를 포착하고 instanceof를 사용하십시오.

$("inuput").live({
    click : function (event) {
        try {
            if (somethingGoesWrong) {
                throw new MyException();
            }
        } catch (Exception) {
            new MyExceptionHandler(Exception);
        }

    }
});

function MyExceptionHandler(Exception) {
    if (Exception instanceof TypeError || 
        Exception instanceof ReferenceError || 
        Exception instanceof RangeError ||  
        Exception instanceof SyntaxError ||     
        Exception instanceof URIError ) {
        throw Exception; // native error
     } else {
         // handle exception
     }
}

MyExcetpionHandler는 try-catch 블록이 없기 때문에 네이티브 오류를 발생시킵니다.

http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/ 방문


4

try-catch항상 최선의 해결책은 아닙니다. 예를 들어 Chrome 7.0에서는 콘솔 창에서 멋진 스택 추적이 손실됩니다. 예외를 다시 던지는 것은 도움이되지 않습니다. 나는 보존이 스택 추적을 모든 솔루션 모르겠어요 그리고 당신은 예외에 반응시키는.


2

약간의 작업으로 모든 브라우저에서 합리적으로 완전한 스택 트레이스를 얻을 수 있습니다.

최신 Chrome 및 Opera (즉, Blink 렌더링 엔진을 기반으로하는 모든 것)는 ErrorEvent 및 window.onerror. 이 두 브라우저에서를 사용 window.onerror하거나 (놀랍게도!) '오류'이벤트에 올바르게 바인딩 할 수 있습니다.

// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
    console.log(message, "from", error.stack);
    // You can send data to your server
    // sendData(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
    console.log(e.error.message, "from", e.error.stack);
    // You can send data to your server
    // sendData(data);
})

불행히도 Firefox, Safari 및 IE는 여전히 주변에 있으며 우리도 지원해야합니다. 스택 트레이스는에서 사용할 수 window.onerror없으므로 조금 더 작업을해야합니다.

오류에서 스택 트레이스를 얻기 위해 할 수있는 유일한 방법은 모든 코드를 try{ }catch(e){ }블록 으로 래핑 한 다음 e.stack을 보는 것입니다. 함수를 가져 와서 오류 처리가 좋은 새 함수를 반환하는 wrap이라는 함수를 사용하여 프로세스를 다소 쉽게 만들 수 있습니다.

function wrap(func) {
    // Ensure we only wrap the function once.
    if (!func._wrapped) {
        func._wrapped = function () {
            try{
                func.apply(this, arguments);
            } catch(e) {
                console.log(e.message, "from", e.stack);
                // You can send data to your server
                // sendData(data);
                throw e;
            }
        }
    }
    return func._wrapped;
};

작동합니다. 수동으로 래핑하는 모든 함수는 오류 처리가 좋습니다.

다음과 같이 이미지 태그를 사용하여 데이터를 보낼 수 있습니다.

function sendData(data) {
    var img = newImage(),
        src = http://yourserver.com/jserror + '&data=' + encodeURIComponent(JSON.stringify(data));

    img.crossOrigin = 'anonymous';
    img.onload = function success() {
        console.log('success', data);
    };
    img.onerror = img.onabort = function failure() {
        console.error('failure', data);
    };
    img.src = src;
}

그러나 데이터를 수집하려면 백엔드를, 데이터를 시각화하려면 프런트 엔드를 수행해야합니다.

에서 Atatus , 우리는이 문제를 해결하기 위해 노력하고 있습니다. 오류 추적 이상으로 Atatus는 실제 사용자 모니터링을 제공합니다.

시도해보십시오 https://www.atatus.com/

면책 조항 : 저는 Atatus의 웹 개발자입니다.


1

최신 브라우저에서는 Ajax 오류에 대한 jQuery 이벤트 핸들러를 추가하는 것과 함께 맨 위로 버블 링되는 오류에 대한 window.onerror 후킹이 클라이언트 코드에서 던진 거의 모든 오류 객체를 포착한다는 것은 사실입니다. window.onerror에 대한 처리기를 수동으로 설정하는 경우 최신 브라우저에서는이 작업이 수행 window.addEventListener('error', callback)되고 IE8 / 9에서는 window.attachEvent('onerror', callback).

그런 다음 이러한 오류가 처리되는 환경과 처리 이유를 고려해야합니다. 스택 추적으로 가능한 한 많은 오류를 포착하는 것이 한 가지이지만, 최신 F12 개발 도구의 출현은 로컬에서 구현하고 디버깅 할 때이 사용 사례를 해결합니다. 중단 점 등은 특히 CORS 요청에서로드 된 타사 라이브러리에서 발생한 오류에 대해 핸들러에서 사용할 수있는 것보다 더 많은 데이터를 제공합니다. 이 데이터를 제공하도록 브라우저에 지시하려면 추가 단계를 수행해야합니다.

핵심 문제는 프로덕션에서이 데이터를 제공하는 것입니다. 사용자는 테스트 할 수있는 것보다 훨씬 더 광범위한 브라우저 및 버전을 실행할 수 있으며 사이트 / 앱은 아무리 많은 QA를 수행하더라도 예기치 않은 방식으로 중단됩니다. 그것.

이를 처리하려면 사용자가 코드를 사용할 때 사용자의 브라우저에서 발생한 모든 오류를 선택하여 데이터를 볼 수있는 엔드 포인트로 전송하고 버그가 발생하면이를 수정하는 데 사용할 수있는 프로덕션 오류 추적기가 필요합니다. . Raygun (면책 조항 : 저는 Raygun에서 일합니다)에 대해 훌륭한 경험을 제공하기 위해 많은 노력을 기울였습니다. 순진한 구현이 놓칠 수 있다고 생각할 수있는 많은 함정과 문제가 있기 때문입니다.

예를 들어, JS 자산을 번들로 묶고 축소 할 가능성이 있습니다. 즉, 축소 된 코드에서 발생한 오류에는 변형 된 변수 이름이있는 정크 스택 트레이스가 포함됩니다. 이를 위해서는 소스 맵을 생성하기위한 빌드 도구 (파이프 라인의이 부분에는 UglifyJS2를 권장합니다)와 오류 추적기가이를 수락하고 처리하여 망가진 스택 추적을 사람이 읽을 수있는 것으로 다시 전환해야합니다. Raygun은이 모든 작업을 즉시 수행하며 빌드 프로세스에서 생성 된 소스 맵을 수락하는 API 엔드 포인트를 포함합니다. 이것은 비공개로 유지되어야하기 때문에 중요합니다. 그렇지 않으면 누구나 코드를 축소하여 목적을 무효화 할 수 있습니다.

raygun4js의 클라이언트 라이브러리도 함께 제공 window.onerrorjQuery를가 아웃 - 오브 - 박스 연결하는대로 그렇게 만 추가해야이 설정하려면뿐만 아니라, 모두 현대적이고 기존 브라우저 :

<script type="text/javascript" src="//cdn.raygun.io/raygun4js/raygun.min.js" </script> <script> Raygun.init('yourApiKey').attach(); </script>

또한 오류를 전송하기 전에 오류 페이로드를 변경하는 기능, 태그 및 사용자 지정 데이터 추가, 오류를 본 사용자에 대한 메타 데이터 등의 기능이 내장되어 있습니다. 또한 위에서 언급 한 타사 CORS 스크립트에서 좋은 스택 추적을 얻는 데 따른 고통을 덜어 주므로 두려운 '스크립트 오류'(오류 메시지와 스택 추적이 포함되지 않음)를 해결합니다.

더 중요한 문제는 웹의 방대한 청중으로 인해 사이트가 각 오류에 대해 수천 개의 중복 인스턴스를 생성한다는 것입니다. Raygun 과 같은 오류 추적 서비스 는이를 오류 그룹으로 롤업 할 수있는 현명한 기능을 갖추고 있으므로 수많은 알림에 빠져들지 않고 수정할 준비가 된 각 실제 오류를 볼 수 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.