Zasady obsługi błędów dla węzła.js + Express.aplikacje js?

Wygląda na to, że raportowanie/obsługa błędów odbywa się inaczej w węźle.js + Express.aplikacje js w porównaniu do innych frameworków. Czy mam rację, rozumiejąc, że działa to w następujący sposób?

A) Wykryj błędy , odbierając je jako parametry do funkcji wywołania zwrotnego. Na przykład:

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

B) Zgłoś błędy w MIDDLEWARE, wywołując next (err). Przykład:

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

C) Raport błędy w trasach poprzez wyrzucenie błędu. Przykład:

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

D) Obsługa błędów poprzez konfigurację własnego programu obsługi błędów za pomocą aplikacji.error() lub użyć generic Connect Error handler. Przykład:

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

Czy te cztery zasady są podstawą do obsługi/raportowania błędów w węźle.js + Express.aplikacje js?

Author: Peter Mortensen, 2011-08-22

3 answers

Obsługa błędów w węźle.js jest na ogół formatu A). Większość wywołań zwrotnych zwraca obiekt błędu jako pierwszy argument or null.

Express.js używa middleware, a składnia middleware używa B) i E) (wymienionych poniżej).

C) to zła praktyka.
app.get('/home', function(req, res) {
    // An error occurs
    throw err;
});

Możesz łatwo przepisać powyższe jako

app.get('/home', function(req, res, next) {
    // An error occurs
    next(err);
});
Składnia Middleware jest ważna w zapytaniu get.

Jak dla D)

(07:26:37 PM) tjholowaychuk: ok.błąd jest usuwany w 3.x

TJ właśnie potwierdził, że app.error jest przestarzałe na rzecz E

E)

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

Każda warstwa pośrednicząca o długości 4 (4 argumenty) jest uważana za warstwę pośredniczącą błędów. Po wywołaniu next(err) connect goes i wywołaniu oprogramowania pośredniczącego opartego na błędach.

 185
Author: Raynos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 10:28:32

Ludzie w Joyent opublikowali naprawdę wnikliwy dokument najlepszych praktyk na ten temat. Artykuł obowiązkowy do przeczytania dla każdego węzła.js developer.

 11
Author: stephbu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-12 15:42:10

Dlaczego pierwszy parametr?

Ze względu na asynchroniczny charakter węzła.js, wzorzec first-parameter-as-err stał się dobrze ugruntowaną konwencją dla węzła userland.obsługa błędów js . Dzieje się tak dlatego, że asynchroniczne:

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

Więc zamiast pierwszego argumentu wywołania zwrotnego jest prawie jedynym sensownym sposobem przekazywania błędów asynchronicznie, innym niż tylko rzucanie ich.

To spowoduje unhandled exception, które, tak jak to dźwięki, oznacza, że nic nie zostało zrobione, aby uzyskać aplikację z jej zdezorientowanego stanu.

Wyjątki, dlaczego istnieją

Warto jednak zauważyć, że praktycznie cała część węzła.js są emiterami zdarzeń, a rzucanie wyjątków jest zdarzeniem niskiego poziomu, które może być obsługiwane jak wszystkie zdarzenia: {]}

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

To może-ale-nie powinno być doprowadzone do skrajności złapać wszystkie błędy i złożyć wniosek, który będzie bardzo starał się nigdy nie zawiesić. To jest okropny pomysł w prawie każdym przypadku użycia, ponieważ pozostawi programistę bez żadnego pojęcia o tym, co dzieje się w stanie aplikacji i jest analogiczny do owijania main w try-catch.

Domeny-grupowanie zdarzeń logicznie

W ramach radzenia sobie z problemem WYJĄTKÓW powodujących upadek aplikacji, domeny pozwalają programistom na wzięcie np. Express.aplikacji js, a także próby sensownego zamykania połączeń w przypadku katastroficznego porażka.

ES6

Prawdopodobnie wspominamy, że to się zmieni ponownie, ponieważ ES6 pozwala wzorzec generatora na tworzenie asynchronicznych zdarzeń, które nadal są chwytalne za pomocą bloków try / catch.

Koa (napisane przez TJ Holowaychuck, tego samego autora Express.js). Używa instrukcji ES6 yield do tworzenia bloków, które, choć wydają się prawie synchroniczne, są obsługiwane w zwykły asynchroniczny sposób węzła:

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');
})

Ten przykład był bezwstydnie skradziony z tutaj .

 3
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 10:35:42