Node.js + Express.js 애플리케이션에 대한 오류 처리 원리?


177

Node.js + Express.js 애플리케이션 에서 오류보고 / 처리가 다른 프레임 워크와 다르게 수행되는 것처럼 보입니다 . 그것이 다음과 같이 작동한다는 것을 이해하는 것이 맞습니까?

A) 콜백 함수에 대한 매개 변수로 오류를 수신하여 오류를 감지 하십시오. 예를 들면 다음과 같습니다.

doSomethingAndRunCallback(function(err) { 
    if(err) {  }
});

B) next (err)를 호출하여 MIDDLEWARE의 오류를 보고하십시오 . 예:

handleRequest(req, res, next) {
    // An error occurs…
    next(err);
}

C) 오류를 발생시켜 ROUTES에 오류를 보고 하십시오. 예:

app.get('/home', function(req, res) {
    // An error occurs
    throw err;
});

D) 핸들 app.error를 통해 자신의 오류 처리기를 구성하여 오류 () 또는 일반 연결 오류 처리기를 사용합니다. 예:

app.error(function(err, req, res, next) {
    console.error(err);
    res.send('Fail Whale, yo.');
});

이 네 가지 원칙이 Node.js + Express.js 애플리케이션의 모든 오류 처리 /보고에 대한 기초입니까?

답변:


183

Node.js의 오류 처리는 일반적으로 A) 형식입니다. 대부분의 콜백은 오류 객체를 첫 번째 인수 또는로 반환합니다 null.

Express.js는 미들웨어를 사용하고 미들웨어 구문은 B) 및 E)를 사용합니다 (아래 참조).

C) 나에게 묻는다면 나쁜 습관이다.

app.get('/home', function(req, res) {
    // An error occurs
    throw err;
});

위와 같이 쉽게 위의 내용을 다시 쓸 수 있습니다

app.get('/home', function(req, res, next) {
    // An error occurs
    next(err);
});

미들웨어 구문은 get요청 에서 유효합니다 .

D는)

(07:26:37 PM) tjholowaychuk : app.error가 3.x에서 제거되었습니다

TJ는 방금 app.errorE에 찬성하여 더 이상 사용되지 않음을 확인했습니다.

이자형)

app.use(function(err, req, res, next) {
  // Only handle `next(err)` calls
});

길이가 4 (4 개의 인수) 인 미들웨어는 오류 미들웨어로 간주됩니다. 하나의 호출이 next(err)연결되면 오류 기반 미들웨어를 호출합니다.


11
감사! 앞으로이 문제를 접할 수있는 사람은 "method e"의 매개 변수 순서가 실제로 err, req, res, next (req, res, next, err 대신) 인 것 같습니다.
클린트 해리스

9
그래서 이것은 멋지게 보이지만, 내가보고있는 문제는 일부 오류가 설명하는 오류 처리기에 절대로 영향을 미치지 않으며 process.on ( 'uncaughtException', fn) 처리기 만 잡을 수 있다는 것입니다. 일반적인 지혜는 그런 일이 일어나도록하고 앱을 다시 시작하기 위해 Forever 등에 의존하는 것이지만 그렇게하면 친숙한 오류 페이지를 어떻게 반환합니까?
Paul

1
@chovy 또한, 단지 fyi. throw / next'd 오류 후에 앱에 오류 처리기를 제공해야합니다 . 이전에 오류가 발생하지 않습니다.
Lee Olayvar

3
다음 (ERR)는 명시 적으로하지만 자신의 미들웨어 내에서 전화를해야 근본적으로 오류를 던지는 익스프레스의 버전입니다
qodeninja

1
@qodeninja이 방법은 Express에서 모범 사례로 간주됩니다.
David Oliveros

11

Joyent의 사람들은 이것에 대한 정말 통찰력있는 모범 사례 문서 를 발표했습니다. Node.js 개발자를위한 필수 기사입니다.



위대한 기사, Joyent의 업데이트 된 문서를 가리 키도록 링크가 수정되었습니다.
stephbu

2
나쁜 기사 : 예제하지만 너무 많은 텍스트와 충분하지가 실제 전문가를위한 기사입니다
게르트

3

왜 첫 번째 매개 변수입니까?

Node.js의 비동기 특성으로 인해 first-parameter-as-err 패턴은 userland Node.js 오류 처리 규칙으로 잘 확립되었습니다 . 비동기이기 때문입니다.

try {
    setTimeout(function() {
        throw 'something broke' //Some random error
    }, 5)
}
catch(e) {
   //Will never get caught
}

따라서 콜백의 첫 번째 인수를 갖는 것이 오류를 던지는 것 이외의 비동기식으로 오류를 전달할 수있는 유일한 방법입니다.

그렇게하면 unhandled exception소리가 나는 방식으로 응용 프로그램을 혼란 상태에서 벗어나기 위해 수행 된 작업이 없음을 의미합니다.

예외, 왜 존재 하는가

그러나 Node.js의 거의 모든 부분이 이벤트 이미 터이고 예외가 발생하면 모든 이벤트처럼 처리 할 수있는 저수준 이벤트라는 점에 주목할 가치가 있습니다.

//This won't immediately crash if connection fails
var socket = require("net").createConnection(5000);
socket.on("error", function(err) {
    console.error("calm down...", err)
});

이것은 -하지만 박사 - 수 있는 극단적으로 취할 수 있는 모든 오류를 포착 하고 열심히 충돌하지하려고합니다 응용 프로그램을 확인합니다. 거의 모든 유스 케이스에서 끔찍한 아이디어입니다. 애플리케이션 상태에서 무슨 일이 일어나고 있는지 전혀 알지 못하고 개발자를 try-catch로 감싸는 것과 비슷하기 때문에 개발자를 떠날 것입니다.

도메인-이벤트를 논리적으로 그룹화

이러한 예외 문제를 해결하는 응용 프로그램 문제의 일부로 개발자는 도메인을 통해 예를 들어 Express.js 응용 프로그램을 사용하여 치명적인 오류가 발생했을 때 현명하게 연결을 끊을 수 있습니다.

ES6

ES6에서 생성기 패턴이 try / catch 블록으로 여전히 캐치 할 수있는 비동기 이벤트를 생성 할 수 있기 때문에 이것이 다시 변경 될 것이라고 언급하고있을 것입니다.

Koa (TJ Holowaychuck, Express.js의 동일한 저자)가이 작업을 눈에 띄게 수행합니다. ES6 yield문을 사용하여 거의 동 기적으로 보이지만 일반적인 노드 비동기 방식으로 처리되는 블록을 만듭니다.

app.use(function *(next) {
    try {
        yield next;
    } 
    catch (err) {
        this.status = err.status || 500;
        this.body = err.message;
        this.app.emit('error', err, this);
    }
});

app.use(function *(next) {
    throw new Error('some error');
})

이 예는 여기서 뻔뻔스럽게 도난당했습니다 .

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