기술 수준에 관계없이 오류 또는 예외는 응용 프로그램 개발자의 수명의 일부입니다. 웹 개발의 불일치로 인해 오류가 발생할 수있는 많은 장소가 남습니다. 해결책의 핵심은 예상치 못한 (또는 예측 가능한 오류)를 처리하여 사용자의 경험을 제어하는 것입니다. JavaScript에서는 문제를 올바르게 해결하는 데 사용할 수있는 다양한 기술 및 언어 기능이 있습니다.
JavaScript의 오류를 처리하는 것은 위험합니다. 머피의 법칙을 믿는다면 결국 무엇이 잘못 될 것인가! 이 기사에서는 JavaScript의 오류 처리를 파헤칩니다. 나는 약간의 함정과 모범 사례를 포함 할 것입니다. 마지막으로 비동기 코드 처리 및 Ajax에 대해 논의 할 것입니다.
JavaScript의 이벤트 중심 모델 이이 언어에 풍부한 의미를 더한다고 생각합니다. 이벤트 중심 엔진과 이러한 종류의 브라우저의 오류보고 메커니즘에는 차이가 없다고 생각합니다. 오류가 발생할 때마다 특정 시점에서 이벤트를 던지는 것과 같습니다. 이론적으로, 우리는 평범한 이벤트를 처리하는 것처럼 JavaScript에서 오류 던지기 이벤트를 처리 할 수 있습니다. 이것이 당신에게 이상하게 들린다면 아래 여행을 시작하는 데 집중하십시오. 이 기사는 클라이언트의 JavaScript 만 대상으로합니다.
예
이 기사에 사용 된 코드 예제는 GitHub에서 얻을 수 있습니다. 현재 페이지는 다음과 같습니다.
각 버튼을 클릭하면 오류가 발생합니다. 타입 원형 유형의 예외를 시뮬레이션합니다. 다음은 이러한 모듈의 정의 및 단위 테스트입니다.
함수 오류 () {var foo = {}; return foo.bar ();}첫째,이 함수는 빈 개체를 정의합니다. Bar () 메소드는 어디에도 정의되지 않습니다. 우리는 단위 테스트를 사용하여 오류가 발생했는지 확인합니다.
it ( 'typeerror를 던지는', function () {thite.throws (target, typeerror);});이 단원 테스트는 Mocha 및해야 할 테스트 어설 션을 사용합니다. JS 라이브러리. Mocha는 실행중인 테스트 프레임 워크이며 JS는 어설 션 라이브러리입니다. 당신이 그들에 익숙하지 않다면, 당신은 온라인으로 그들의 문서를 무료로 찾아 볼 수 있습니다. 테스트 사례는 일반적으로 그것 ( '설명')으로 시작하여 주장의 전달 또는 실패로 끝납니다. 이 프레임 워크를 사용하는 장점은 브라우저가 아닌 노드에서 단위 테스트를 할 수 있다는 것입니다. JavaScript의 많은 주요 기본 개념을 검증하기 때문에 이러한 테스트를 심각하게 수행하는 것이 좋습니다.
위에서 볼 수 있듯이 Error ()는 빈 객체를 정의한 다음 메소드를 호출하려고합니다. 이 객체에는 bar () 메소드가 존재하지 않기 때문에 예외가 발생합니다. JavaScript와 같은 역동적 인 언어로 누구나 그러한 실수를 할 수 있습니다.
나쁜 시연
잘못된 오류 처리 방법을 살펴 보겠습니다. 나는 잘못된 행동을 추상화하고 버튼에 바인딩 할 것입니다. 핸들러의 단위 테스트는 다음과 같습니다.
함수 badhandler (fn) {try {return fn (); } catch (e) {} return null;}이 처리 함수는 종속성으로 콜백 함수 FN을 수신합니다. 그런 다음 기능이 핸들러 내부에서 호출됩니다. 이 단위 테스트 예제이 방법을 사용하는 방법.
( '오류없이 값을 반환', function () {var fn = function () {return 1;}; var result = target (fn); result. equal (1);}); it ( '오류가있는 null을 반환합니다', function () {tash error ( 'random error'); var result = target (fn); (result) .equal (null);});보시다시피, 오류가 발생하면이 이상한 취급 방법은 널을 반환합니다. 이 콜백 함수 fn ()은 법적 메소드 또는 오류를 가리 킵니다. 아래 클릭 처리 이벤트는 나머지를 완료합니다.
(기능 (핸들러, 폭탄) {var badbutton = docum나쁜 점은 내가 방금 얻은 것이 무인이라는 것입니다. 이것은 내가 무엇이 잘못되었는지 결정할 때 나를 매우 혼란스럽게 만들었습니다. 오류가 발생할 때 의이 침묵 전략은 사용자 경험 설계에서 데이터 손상에 이르기까지 모든 링크를 포함합니다. 이후의 좌절 측면은 디버깅 시간을 소비해야했지만 Try-Catch 코드 블록에서 오류를 볼 수 없다는 것이 었습니다. 이 이상한 처리는 코드의 모든 오류를 숨기고 모든 것이 정상이라고 가정합니다. 코드 품질에주의를 기울이지 않는 일부 팀에서는 원활하게 실행할 수 있습니다. 그러나 이러한 숨겨진 오류는 결국 코드를 디버깅하는 데 몇 시간을 소비해야합니다. 통화 스택에 의존하는 다층 솔루션에서 오류의 출처를 결정할 수 있습니다. 드문 경우에 시도 캐치를 조용히 처리하는 것이 적절할 수 있습니다. 그러나 오류가 발생하면 오류가 발생하면 좋은 해결책이 아닙니다.
이 실패는 침묵 전략이므로 코드의 오류를 더 잘 처리해야합니다. JavaScript는 이러한 유형의 문제를 처리하는보다 우아한 방법을 제공합니다.
읽을 수없는 솔루션
계속해서 이해하기 어려운 접근 방식을 살펴 보겠습니다. 나는 단단히 결합 된 부분을 DOM과 건너 뛸 것이다. 이 부분은 우리가 방금 본 나쁜 접근 방식과 다르지 않습니다. 초점은 예외를 처리하는 아래 단위 테스트의 일부에 있습니다.
함수 uglyhandler (fn) {try {return fn (); } catch (e) {Throw Error ( '새 오류'); }} it ( '오류가있는 새 오류를 반환합니다', function () {var fn = function () {새 typeError ( 'type error');}; throws (function () {target (fn);}, error);});지금은 나쁜 치료에 비해 좋은 개선이 있습니다. 콜 스택에 예외가 발생합니다. 내가 좋아하는 것은 오류가 스택에서 해제되며 디버깅에 큰 도움이된다는 것입니다. 예외가 발생하면 통역사는 다음 프로세싱 기능을 통화 스택의 수준에서 살펴 봅니다. 이는 통화 스택의 최상위 레벨에서 오류를 처리 할 수있는 많은 기회를 제공합니다. 불행히도, 그는 어려운 실수이기 때문에 원래 오류 정보를 볼 수 없습니다. 따라서 콜 스택을 따라보고 가장 원시적 인 예외를 찾아야합니다. 그러나 적어도 나는 예외가 발생하는 오류가 발생한다는 것을 알고 있습니다.
이 읽을 수없는 오류 처리는 무해하지만 코드를 이해하기 어렵게 만듭니다. 브라우저가 어떻게 오류를 처리하는지 살펴 보겠습니다.
전화 스택
그런 다음 예외를 던지는 한 가지 방법은 시도를 추가하는 것입니다 ... 통화 스택의 최상위 레벨에서 코드 블록을 잡는 것입니다. 예를 들어:
함수 main (bomb) {try {bomb (); } catch (e) {// 모든 오류 처리}}}그러나 브라우저가 이벤트 중심이라고 말한 것을 기억하십니까? 예, JavaScript의 예외는 이벤트에 지나지 않습니다. 통역사는 현재 예외가 발생하고있는 상황에서 프로그램을 중지하고 예외를 발생시킵니다. 이를 확인하기 위해 다음은 우리가 볼 수있는 글로벌 이벤트 처리 기능입니다. 다음과 같이 보입니다.
window.adeventListener ( 'error', function (e) {var error = e.error; console.log (error);});이 이벤트 핸들러는 실행 환경에서 오류를 포착합니다. 오류 이벤트는 다양한 장소에서 다양한 오류가 발생합니다. 이 접근법의 요점은 코드의 중앙에 오류를 처리하는 것입니다. 다른 이벤트와 마찬가지로 글로벌 핸들러를 사용하여 다양한 오류를 처리 할 수 있습니다. 이렇게하면 단일 책임 (단일 책임, 개방형, Liskov 대체, 인터페이스 분리 및 종속성 반전)을 고수하는 경우 오류 처리가 단일 목표 만 만듭니다. 언제든지 오류 처리 기능을 등록 할 수 있습니다. 통역사는 이러한 기능 루프를 실행합니다. 코드는 시도로 가득 찬 진술에서 해제됩니다 ... 캐치와 디버그가 쉬워집니다. 이 접근법의 핵심은 일반적인 JavaScript 이벤트와 마찬가지로 발생하는 오류를 처리하는 것입니다.
이제 글로벌 처리 기능으로 통화 스택을 표시하는 방법이 있습니다. 우리는 그것으로 무엇을 할 수 있습니까? 결국, 우리는 통화 스택을 사용해야합니다.
통화 스택을 기록하십시오
통화 스택은 버그 수정을 처리하는 데 매우 유용합니다. 좋은 소식은 브라우저 가이 정보를 제공한다는 것입니다. 오류 객체의 스택 속성이 현재 표준이 아니지만이 속성은 일반적으로 최신 브라우저에서 지원됩니다.
따라서 우리가 할 수있는 멋진 일은 서버에 인쇄하는 것입니다.
window.adeventListener ( 'error', function (e) {var stack = e.error.stack; var message = e.error.tostring (); if (stack) {message + = '/n' + stack;} var xhr = new xmlhttprequest (); xhr.open ( 'post', ');코드 예제에서는 분명하지 않을 수 있지만이 이벤트 핸들러는 이전 오류 코드에 의해 트리거됩니다. 위에서 언급했듯이 각 핸들러는 단일 목적을 가지므로 코드를 건조하게합니다 (반복적으로 휠을 만들지 않고 반복하지 마십시오). 내가 관심있는 것은 서버에서 이러한 메시지를 캡처하는 방법입니다.
다음은 노드 런타임의 스크린 샷입니다.
통화 스택은 코드를 디버깅하는 데 매우 유용합니다. 콜 스택의 역할을 과소 평가하지 마십시오.
비동기 처리
아, 비동기 코드를 처리하는 것은 매우 위험합니다! JavaScript는 현재 실행 환경에서 비동기 코드를 가져옵니다. 이것은 아래의 시도에 문제가 있음을 의미합니다.
함수 asynchandler (fn) {try {settimeout (function () {fn ();}, 1); } catch (e) {}}이 단원 테스트의 나머지 부분이 여전히 있습니다.
( '오류 () {var fn = function () {new typeError ('type error ');}; 실패한 프로모스 (function () {target (fn);}). });}예외를 확인하겠다는 약속 으로이 핸들러를 끝내야합니다. 내 코드가 모두 시도되어 있지만 ... 캐치가 모두 있지만, 도대치되지 않은 예외는 여전히 나타납니다. 예, 시도해보십시오 ... 캐치는 별도의 실행 환경에서만 작동합니다. 예외가 발생하면 통역사의 실행 환경은 더 이상 현재 트리 캐치 블록이 아닙니다. 이 동작은 Ajax 호출과 유사하게 발생합니다. 이제 두 가지 옵션이 있습니다. 대안은 비동기 콜백에서 예외를 포착하는 것입니다.
settimeout (function () {try {fn ();} catch (e) {//이 비동기 오류}, 1);이 방법은 유용하지만 개선의 여지가 여전히 많습니다. 먼저, 코드 블록을 잡는 코드 블록은 코드의 모든 곳에 나타납니다. 실제로 1970 년대 프로그래밍 전화에서 그들은 코드가 무너지기를 원했습니다. 또한 V8 엔진은 시도 사용을 권장하지 않습니다… 기능의 코드 블록을 잡아 당깁니다 (V8은 Chrome 브라우저 및 노드에서 사용하는 JavaScript 엔진). 통화 스택 상단에서 예외를 포착하는 코드 블록을 작성하는 것이 좋습니다.
그렇다면 이것이 우리에게 무엇을 말합니까? 위에서 말했듯이, 실행 컨텍스트의 전역 오류 처리기가 필요합니다. 창 객체에 오류 핸들러를 추가하면 완료됩니다! 건조하고 견고한 원칙을 따르는 것이 좋지 않습니까? 글로벌 오류 핸들러는 코드를 읽을 수 있고 깨끗하게 유지합니다.
다음은 서버 측 예외 처리에 인쇄 된 보고서입니다. 예제에서 코드를 사용하면 사용중인 브라우저에 따라 출력이 약간 다를 수 있습니다.
이 핸들러는 비동기 코드에서 어떤 오류가 발생하는지 알려줄 수도 있습니다. 오류는 settimeout () 핸들러에서 나옵니다. 너무 멋져요!
오류는 모든 응용 프로그램의 일부이지만 적절한 오류 처리는 아닙니다. 오류를 처리하는 방법에는 두 가지가 있습니다. 하나는 실패, 침묵, 즉 코드의 오류를 무시합니다. 또 다른 방법은 오류를 신속하게 감지하고 해결하는 것입니다. 즉, 오류를 중지하고 재생산합니다. 나는 내가 좋아하는 것과 왜 그것을 좋아하는지 명확하게 표현했다고 생각합니다. 내 선택 : 문제를 숨기지 마십시오. 당신의 프로그램에서 예상치 못한 이벤트에 대해 아무도 당신을 비난하지 않을 것입니다. 이것은 포인트를 깨고 재생산하고 사용자에게 시도하는 것이 허용됩니다. 불완전한 세상에서는 기회를주는 것이 중요합니다. 오류는 불가피하며 오류를 해결하는 데 중요합니다. JavaScript의 오류 처리 기능과 자동 및 유연한 디코딩을 합리적으로 사용하면 사용자의 경험을 더 매끄럽게 만들 수 있으며 개발자의 진단이 더 쉬워 질 수 있습니다.