JavaScript Error_javascript 팁을 캡처하고 분석하는 방법

WBOY
풀어 주다: 2016-05-16 16:54:37
원래의
1181명이 탐색했습니다.

JavaScript 오류를 캡처하고 분석하는 방법

프런트엔드 엔지니어는 모두 JavaScript에 기본적인 예외 처리 기능이 있다는 것을 알고 있습니다. new Error()를 던질 수 있고, API를 호출할 때 오류가 발생하면 브라우저도 예외를 던질 것입니다. 하지만 대부분의 프론트엔드 엔지니어들은 이러한 비정상적인 정보 수집을 고려한 적이 없는 것으로 추정됩니다. 어쨌든 새로 고침 후 JavaScript 오류가 다시 나타나지 않는 한 사용자는 새로 고침을 통해 문제를 해결할 수 있으며 브라우저는 충돌하지 않으며 발생하지 않은 것처럼 처리할 수 있습니다. 이 가정은 단일 페이지 앱이 대중화되기 전에는 사실이었습니다. 현재 단일 페이지 앱의 상태는 일정 기간 동안 실행된 후 매우 복잡해집니다. 사용자가 여기에 도착하기 전에 여러 가지 입력 작업을 수행했을 수 있습니다. 새로 고쳐진다고 하면 새로 고쳐야 할까요? 이전 작업을 완전히 다시 수행해야 하는 것 아닌가요? 따라서 이러한 예외 정보를 캡처하고 분석한 다음 사용자 경험에 영향을 주지 않도록 코드를 수정할 수 있습니다.
예외를 잡는 방법

우리는 throw new Error()를 직접 작성했습니다. 물론 우리는 throw가 작성된 위치를 정확히 알고 있기 때문에 원할 경우 이를 잡을 수 있습니다. 그러나 브라우저 API를 호출할 때 발생하는 예외는 반드시 잡기 쉬운 것은 아닙니다. 일부 API는 예외를 발생시키도록 표준에 작성되어 있으며, 일부 API는 구현 차이 또는 결함으로 인해 개별 브라우저에서만 발생합니다. 전자의 경우 try-catch를 통해 이를 포착할 수도 있습니다. 후자의 경우 전역 예외를 수신한 다음 이를 포착해야 합니다.

try-catch

일부 브라우저 API가 예외를 발생시키는 것으로 알려진 경우 오류로 인해 전체 프로그램이 시작되는 것을 방지하기 위해 호출을 try-catch에 넣어야 합니다. . 예를 들어, window.localStorage는 데이터 쓰기가 용량 제한을 초과하면 예외를 발생시킵니다. 이는 Safari의 개인 탐색 모드에서도 마찬가지입니다.

코드 복사 코드는 다음과 같습니다.

try {
localStorage.setItem( 'date' , Date.now());
} catch(error) {
reportError(error);
}

또 다른 일반적인 try-catch 적용 시나리오는 콜백입니다. . 콜백 함수의 코드는 우리가 통제할 수 없기 때문에 코드의 품질이나 예외를 발생시키는 다른 API가 호출되는지 여부에 대해 알 수 없습니다. 콜백을 호출한 후 다른 코드가 콜백 오류로 인해 실행되지 않는 것을 방지하려면 콜백을 try-catch에 다시 넣어야 합니다.
코드 복사 코드는 다음과 같습니다.

listeners.forEach(function(listener) {
try {
listener();
} catch(오류) {
reportError(error)
}
}); >

try-catch가 적용되지 않는 영역의 경우 예외가 발생하면 window.onerror를 통해서만 캡처할 수 있습니다.


코드 복사 코드는 다음과 같습니다. window.onerror =
function( errorMessage, scriptURI , lineNumber) {
reportError({
message: errorMessage,
script: scriptURI,
line: lineNumber
})
}


창문을 사용하지 않도록 주의하고 window.addEventListener 또는 window.attachEvent를 사용하여 window.onerror를 수신하세요. 많은 브라우저에서는 window.onerror만 구현하거나 window.onerror 구현만 표준입니다. 표준 초안에서도 window.onerror를 정의하고 있다는 점을 고려하면 그냥 window.onerror를 사용해도 됩니다.
속성 손실

캡처된 예외를 수집한 다음 쿼리 및 분석을 위해 일괄적으로 서버측 저장소로 보내는 reportError 함수가 있다고 가정해 보겠습니다. 그렇다면 우리가 수집하려는 정보는 무엇입니까? 더 유용한 정보에는 오류 유형(이름), 오류 메시지(메시지), 스크립트 파일 주소(script), 줄 번호(line), 열 번호(column) 및 스택 추적(stack)이 포함됩니다. try-catch를 통해 예외가 포착되면 이 정보는 Error 개체(주요 브라우저에서 지원됨)에 있으므로 reportError도 이 정보를 수집할 수 있습니다. 하지만 window.onerror를 통해 캡처하면 이 이벤트 함수에는 3개의 매개변수만 있으므로 이 3개 매개변수 이외의 정보는 손실된다는 것을 우리 모두 알고 있습니다.
직렬화된 메시지

Error 객체가 스스로 생성된 경우 error.message는 우리가 제어합니다. 기본적으로 우리가 error.message에 무엇을 입력하든 window.onerror의 첫 번째 매개변수(메시지)가 됩니다. (브라우저는 실제로 'Uncaught Error:' 접두사를 추가하는 등 약간의 수정을 합니다.) 따라서 우리가 관심 있는 속성(예: JSON.Stringify)을 직렬화하고 이를 error.message에 저장한 다음 읽을 수 있습니다. window.onerror에서 꺼내서 역직렬화하세요. 물론 이는 우리가 직접 생성한 Error 개체로 제한됩니다.
다섯 번째 매개변수

브라우저 제조사들도 window.onerror를 사용할 때 모든 사람이 직면하는 한계를 알고 있었기 때문에 window.onerror에 새로운 매개변수를 추가하기 시작했습니다. 행 번호만 있고 열 번호가 없는 것을 고려하여 IE는 먼저 열 번호를 추가하고 이를 네 번째 매개 변수에 넣습니다. 그러나 모든 사람들은 완전한 스택을 얻을 수 있는지에 대해 더 관심을 갖고 있으므로 Firefox는 스택을 다섯 번째 매개 변수에 넣는 것이 더 나을 것이라고 말했습니다. 하지만 Chrome에서는 전체 Error 개체를 다섯 번째 매개변수에 넣는 것이 더 낫다고 말했습니다. 맞춤 속성을 포함하여 원하는 모든 속성을 읽을 수 있습니다. 결과적으로 Chrome은 더 빠르게 움직이고 Chrome 30에서 새로운 window.onerror 서명을 구현하여 이에 따라 표준 초안이 작성되었습니다.
코드 복사 코드는 다음과 같습니다.

window.onerror = function(
errorMessage,
scriptURI,
lineNumber,
columnNumber,
error
) {
if (오류) {
reportError(오류)
} else {
reportError( {
메시지: errorMessage,
script: scriptURI,
line: lineNumber,
column: columnNumber
})


속성 정규화

이전에 논의한 Error 개체 속성의 이름은 Chrome 명명 방법을 기반으로 합니다. 그러나 Chrome에서는 스크립트 파일 주소와 같이 브라우저마다 다른 방식으로 Error 개체 속성의 이름을 지정합니다. 스크립트라고 부르지만 Firefox에서는 파일 이름이라고 합니다. 따라서 Error 객체를 정규화하는, 즉 서로 다른 속성 이름을 통합된 속성 이름에 매핑하는 특수 함수도 필요합니다. 구체적인 방법은 이 글을 참고하세요. 브라우저 구현이 업데이트되더라도 이러한 매핑 테이블을 수동으로 유지 관리하는 것은 그리 어렵지 않습니다.

스택 추적 형식과 유사합니다. 이 속성은 예외 정보 스택을 일반 텍스트 형식으로 저장합니다. 각 브라우저에서 사용하는 텍스트 형식이 다르기 때문에 일반 텍스트에서 각 프레임의 기능을 추출하려면 정규식을 수동으로 유지해야 합니다. 식별자), 파일(스크립트), 줄 번호(line) 및 열 번호(열)입니다.
보안 제한

'스크립트 오류' 메시지와 함께 오류가 발생했다면 실제로는 다른 원본 스크립트 파일에 대한 브라우저의 응답을 이해하게 될 것입니다. 이러한 보안 제한의 이유는 사용자가 로그인한 후 온라인 은행에서 반환한 HTML이 익명 사용자가 본 HTML과 다르다고 가정하면 제3자 웹사이트에서 온라인 은행의 URI를 스크립트에 넣을 수 있기 때문입니다. src 속성. 물론 HTML은 JS로 구문 분석할 수 없으므로 브라우저에서는 예외가 발생하며, 타사 웹사이트에서는 예외 위치를 구문 분석하여 사용자가 로그인했는지 여부를 확인할 수 있습니다. 이러한 이유로 브라우저는 '스크립트 오류'와 같은 변경되지 않은 메시지가 하나만 남고 다른 모든 속성이 사라질 때까지 다양한 소스의 스크립트 파일에서 발생하는 모든 예외를 필터링합니다.

특정 규모의 웹사이트에서는 스크립트 파일이 다양한 소스의 CDN에 배치되는 것이 일반적입니다. 이제 자신만의 작은 웹사이트를 구축하더라도 jQuery 및 Backbone과 같은 일반적인 프레임워크는 공개 CDN의 버전을 직접 참조하여 사용자 다운로드 속도를 높일 수 있습니다. 따라서 이러한 보안 제한은 일부 문제를 야기하여 Chrome 및 Firefox에서 수집한 예외 정보가 쓸모없는 '스크립트 오류'가 되도록 만듭니다.
CORS

이 제한을 우회하려면 스크립트 파일과 페이지 자체의 출처가 동일한지 확인하세요. 그런데 CDN으로 가속되지 않는 서버에 스크립트 파일을 놓으면 사용자의 다운로드 속도가 느려지지 않나요? 한 가지 해결 방법은 계속해서 CDN에 스크립트 파일을 배치하고 XMLHttpRequest를 사용하여 CORS를 통해 콘텐츠를 다시 다운로드한 다음 <script> 태그를 만들어 페이지에 삽입하는 것입니다. 페이지에 포함된 코드는 물론 동일한 소스에서 가져온 것입니다. <br><br>간단해 보이지만 구현해야 할 세부 사항이 많습니다. 간단한 예를 들어보겠습니다. <br><div class="codetitle"> <span><a style="CURSOR: pointer" data="8772" class="copybut" id="copybut8772" onclick="doCopy('code8772')"><u>코드 복사 </u></a></span> 코드는 다음과 같습니다. </div> <div class="codebody" id="code8772"> <br><script src ="http://cdn.com/step1.js"></script>
<script> <br>(function step2() {})(); ; <br><script src="http://cdn.com/step3.js"></script>

우리 모두는 1단계, 2단계, 3단계가 있다면 알고 있습니다. 종속성 그렇다면 이 순서를 엄격히 따라야 합니다. 그렇지 않으면 오류가 발생할 수 있습니다. 브라우저는 step1과 step3의 파일을 병렬로 요청할 수 있지만 실행 중에는 순서가 보장됩니다. XMLHttpRequest를 통해 step1과 step3의 파일 내용을 직접 얻는 경우 순서가 올바른지 확인해야 합니다. 또한 step2는 step1이 비차단 방식으로 다운로드될 때 실행될 수 있으므로 step1을 실행하기 전에 step1이 완료될 때까지 기다리도록 수동으로 개입해야 합니다.

웹사이트의 여러 페이지에 대해 <script> 태그를 생성하는 도구 세트가 이미 있는 경우 이 도구 세트를 조정하여 <script> 태그를 변경해야 합니다. <br> <br><div class="codetitle"><span><a style="CURSOR: pointer" data="91019" class="copybut" id="copybut91019" onclick="doCopy('code91019')">코드 복사<u></u></a> 코드는 다음과 같습니다.</span></div> <div class="codebody" id="code91019"><script> //cdn.com/step1.js'); <br><script> <br>scheduleInlineScript(function code() { <br>(function step2() {})() ; <br> }) <br></script>
<script>scheduleRemoteScript('http://cdn.com/step3.js'); <br><br><br>다음으로 주소를 기반으로 ScheduleRemoteScript로 다운로드한 파일 콘텐츠와 ScheduleInlineScript로 직접 얻은 코드가 올바른 순서로 차례로 실행될 수 있도록 완전한 메커니즘을 구현해야 합니다. 여기서는 자세한 코드를 제공하지 않겠습니다. 관심이 있으시면 직접 구현해 보세요. <br>줄 번호 역 확인 <br><br>CORS를 통해 콘텐츠를 가져온 다음 페이지에 코드를 삽입하면 보안 제한을 뚫을 수 있지만 새로운 문제, 즉 줄 번호 충돌이 발생합니다. 원래는 error.script를 사용하여 고유한 스크립트 파일을 찾을 수 있었고 error.line을 사용하여 고유한 줄 번호를 찾을 수 있었습니다. 이제 페이지에 포함된 코드이므로 여러 개의 <script> 태그를 error.script로 구분할 수 없습니다. 그러나 각 <script> 태그 안의 줄 번호는 1부터 시작합니다. 오류가 있는 소스 코드 위치를 찾는 데 사용됩니다. <br><br>줄 번호 충돌을 피하기 위해 각 <script> 태그의 실제 코드에서 사용하는 줄 번호 범위가 서로 겹치지 않도록 일부 줄 번호를 낭비할 수 있습니다. 예를 들어, 각 <script> 태그의 실제 코드가 1000줄을 넘지 않는다고 가정하면 첫 번째 <script> 태그의 코드는 1~1000줄을 차지하고 두 번째 코드는 <script> 태그는 1001~2000행(그 앞에 1000개의 빈 행 삽입)을 차지하고 세 번째 <script> 태그의 코드는 2001~3000행(그 앞에 2000개의 빈 행을 삽입)을 차지합니다. 그런 다음 data-* 속성을 사용하여 쉽게 검색할 수 있도록 이 정보를 기록합니다. <br><br><div class="codetitle"><span><a style="CURSOR: pointer" data="17722" class="copybut" id="copybut17722" onclick="doCopy('code17722')">코드 복사<u></u></a> 코드는 다음과 같습니다.</span></div> <div class="codebody" id="code17722"><script <BR>data-src ="http ://cdn.com/step1.js" <BR>data-line-start="1" <BR>> <br>// 1단계 코드 <br></script> >< script data-line-start="1001">
// 'n' * 1000
// 2단계 코드



이러한 처리 후 오류의 error.line이 3005이면 실제 error.script는 'http://cdn.com/step3.js'여야 하고 실제 error.line은 3005라는 뜻입니다. 5이어야 합니다. 앞서 언급한 reportError 함수에서 이 줄 번호 역방향 검사를 완료할 수 있습니다.

물론 각 스크립트 파일에 1000줄만 있다고 보장할 수 없고 일부 스크립트 파일은 1000줄보다 훨씬 작을 수 있으므로 각 < 스크립트> 각
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿