Принципы обработки ошибок для приложений Node.js + Express.js? - PullRequest
175 голосов
/ 22 августа 2011

В приложениях Node.js + Express.js создается впечатление, что сообщения об ошибках и их обработка выполняются иначе, чем в других средах. Правильно ли я понимаю, что это работает следующим образом?

A) Обнаружение ошибок путем получения их в качестве параметров для функций обратного вызова. Например:

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

B) Сообщите об ошибках в MIDDLEWARE, вызвав next (err). Пример:

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

C) Сообщите об ошибках в МАРШРУТАХ, выдав ошибку. Пример: * 1 023 *

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

D) Обрабатывать ошибки, настраивая свой собственный обработчик ошибок через app.error () или используя универсальный обработчик ошибок Connect. Пример:

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

Являются ли эти четыре принципа основой для обработки ошибок / составления отчетов в приложениях Node.js + Express.js?

Ответы [ 3 ]

182 голосов
/ 22 августа 2011

Обработка ошибок в 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.er удалена в 3.x

TJ только что подтвердил, что app.error устарел в пользу E

E)

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

Любое промежуточное программное обеспечение, имеющее длину 4 (4 аргумента), считается промежуточным программным обеспечением ошибки. Когда вы звоните next(err), происходит соединение и вызывает промежуточное ПО на основе ошибок.

10 голосов
/ 20 февраля 2015

Люди в Joyent опубликовали действительно проницательный документ о лучших практиках по этому вопросу.Обязательно прочитайте статью для любого разработчика Node.js.

3 голосов
/ 16 марта 2015

Почему первый параметр?

Из-за асинхронного характера 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)
});

Это может-но-не следует доводить до крайности, чтобы перехватить все ошибки и создать приложение, которое будет очень стараться, чтобы никогда не вылетело.Это ужасная идея почти во всех случаях использования, поскольку она оставляет разработчика без представления о том, что происходит в состоянии приложения, и аналогична переносу main в try-catch.

Домены - группировка событийлогически

В рамках решения этой проблемы исключений, вызывающих сбой приложений, домены позволяют разработчику использовать, например, приложение Express.js, и пытаться разумно закрывать соединения всобытие катастрофического сбоя.

ES6

Вероятно, следует упомянуть, что это снова изменится, поскольку ES6 позволяет образцу генератора создавать асинхронные события, которые по-прежнему могут быть перехвачены с помощью блоков try / catch.

Коа (автор 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');
})

Этот пример был бесстыдно украден из здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...