2012-10-30 8 views
77

Próbowałem znaleźć dobry opis tego, co robi metoda next(). W dokumentacji Express mówi, że można użyć next('route'), aby przeskoczyć do tej trasy i pominąć wszystkie trasy pomiędzy, ale czasami next jest wywoływana bez argumentów. Ktoś wie o dobrym samouczku itp. Opisującym funkcję next?Ekspresowa następna funkcja, po co tak naprawdę jest?

Odpowiedz

105

next() bez argumentów mówi "tylko żartuję, ja naprawdę nie chcę sobie z tym poradzić". Wraca i próbuje znaleźć następną pasującą trasę.

Jest to użyteczne, powiedzmy, jeśli chcesz mieć jakiegoś menedżera stron z url slugs, a także wiele innych rzeczy, ale oto przykład.

app.get('/:pageslug', function(req, res, next){ 
    var page = db.findPage(req.params.pageslug); 
    if (page) { 
    res.send(page.body); 
    } else { 
    next(); 
    } 
}); 

app.get('/other_routes', function() { 
    //... 
}); 

To składa się kod należy sprawdzić bazę danych na stronie z pewnym ślimak id. Jeśli znajdzie, wyrenderuj! jeśli go nie znajdzie, zignoruj ​​tę procedurę obsługi i sprawdź inne.

Tak więc next() bez argumentów pozwala udawać, że nie obsługiwałeś trasy, aby coś innego mogło ją odebrać.


Lub licznik trafień z app.all('*'). Który pozwala ci wykonać jakiś wspólny kod konfiguracji, a następnie przejść do innych tras, aby zrobić coś bardziej konkretnego.

app.all('*', function(req, res, next){ 
    myHitCounter.count += 1; 
    next(); 
}); 

app.get('/other_routes', function() { 
    //... 
}); 
+0

Świetna odpowiedź! Widziałem inne wykorzystanie następnych również, np. next (err) i next ("route"). Czy teraz masz na to cel, kiedy chcesz propagować błąd i kiedy chcesz przeskoczyć na określoną trasę? –

+7

@AndreasSelenwall 'next ('route')' jest specyficzne dla ['app.VERB()'] (http://expressjs.com/api.html#app.VERB) i jest używane, gdy trasa ma wiele wywołań zwrotnych "* ominąć pozostałe wywołania zwrotne trasy. *" 'next (err)' służy do przechodzenia do dowolnego "[middleware] błędu (http://stackoverflow.com/a/7151775/15031)" ('E' z postu). –

+2

Rewizja. Tylko dla tego zwrotu: "tylko żartuję, nie chcę tego znieść" sprawiłeś, że zrozumiałem, czego szukałem. Widziałem wiele podobnych pytań i znalazłem rozwiązanie w jednym zdaniu. –

102

W większości schematów pojawi się żądanie i użytkownik chce zwrócić odpowiedź. Ze względu na asynchroniczną naturę Node.js napotkasz problemy z zagnieżdżonymi oddzwanianiem, jeśli robisz inne trywialne rzeczy. Aby tego uniknąć, program Connect.js (wcześniejszy niż wersja 4.0, Express.js był warstwą na wierzchu connect.js) ma coś, co nazywa się oprogramowaniem pośredniczącym, które jest funkcją z 2, 3 lub 4 parametrami.

Twoja aplikacja Express.js to stos tych funkcji.

enter image description here

Router jest wyjątkowy, to middleware, który pozwala wykonać jedną lub więcej middleware dla pewnego URL. Więc to stos wewnątrz stosu.

Co dalej? Proste, informuje twoją aplikację, aby uruchomiła następne oprogramowanie pośredniczące. Ale co się stanie, gdy przekażesz coś do następnego? Express przerwie bieżący stos i uruchomi wszystkie oprogramowanie pośrednie, które ma 4 parametry.

function (err, req, res, next) {} 

To oprogramowanie pośrednie służy do przetwarzania wszelkich błędów. Chciałbym wykonać następujące czynności:

next({ type: 'database', error: 'datacenter blew up' }); 

Z tym błędem prawdopodobnie powiedziałbym użytkownikowi, że coś poszło nie tak i zaloguj prawdziwy błąd.

function (err, req, res, next) { 
    if (err.type === 'database') { 
    res.send('Something went wrong user'); 
    console.log(err.error); 
    } 
}; 

Jeśli obrazujesz aplikację Express.js jako stos, prawdopodobnie będziesz w stanie samodzielnie naprawić wiele dziwności. Na przykład po dodaniu oprogramowania pośredniczącego do plików cookie po routerze ma sens, że twoje trasy nie będą zawierać plików cookie.

+7

Doskonała odpowiedź. –

+3

Gdzie przechowywałbyś tę anonimową funkcję logowania? – dennismonsewicz

5

next() bez parametru wywołuje następny przewodnik obsługi trasy w strukturze.

+0

Lub następne oprogramowanie pośredniczące. – robertklep

18

IMHO, przyjęta odpowiedź na to pytanie nie jest prawdziwa. Jak stwierdzili inni, chodzi o kontrolowanie, kiedy kolejny handler w łańcuchu jest uruchamiany. Ale chciałem podać trochę więcej kodu, aby było bardziej konkretne. Załóżmy, że masz ten prosty ekspresowe app:

var express = require('express'); 
var app = express(); 

app.get('/user/:id', function (req, res, next) { 
    console.log('before request handler'); 
    next(); 
}); 

app.get('/user/:id', function (req, res, next) { 
    console.log('handling request'); 
    res.sendStatus(200); 
    next(); 
}); 

app.get('/user/:id', function (req, res, next) { 
    console.log('after request handler'); 
    next(); 
}); 

app.listen(3000, function() { 
    console.log('Example app listening on port 3000!') 
}); 

Jeśli nie

curl http://localhost:3000/user/123 

widać to wydrukowane pocieszyć:

before request handler 
handling request 
after request handler 

Teraz, jeśli wykomentuj wezwanie do next() w taki pośrednik:

app.get('/user/:id', function (req, res, next) { 
    console.log('handling request'); 
    res.sendStatus(200); 
    //next(); 
}); 

będzie to zobaczyć na konsoli:

before request handler 
handling request 

Zauważ, że ostatni obsługi (ten, który drukuje after request handler) nie działa. To dlatego, że nie mówisz już ekspresowi, aby uruchomić następny handler.

Więc to naprawdę nie ma znaczenia, czy „main” treser (ten, który zwraca 200) był udany, czy nie, jeśli chcesz reszta middleware biec, trzeba zadzwonić next().

Kiedy to się przyda? Powiedzmy, że chcesz rejestrować wszystkie żądania, które trafiły do ​​pewnej bazy danych, niezależnie od tego, czy żądanie się powiodło.

app.get('/user/:id', function (req, res, next) { 
    try { 
     // ... 
    } 
    catch (ex) { 
     // ... 
    } 
    finally { 
     // go to the next handler regardless of what happened in this one 
     next(); 
    } 
}); 

app.get('/user/:id', function (req, res, next) { 
    logToDatabase(req); 
    next(); 
}); 

Jeśli chcesz drugą obsługi, aby uruchomić, trzeba zadzwonić next() w pierwszym obsługi.

Należy pamiętać, że węzeł jest asynchroniczny, więc nie wie, kiedy nastąpiło wywołanie zwrotne pierwszego programu obsługi. Musisz to powiedzieć, dzwoniąc pod numer next().

+0

To jest naprawdę jasne wytłumaczenie. Dzięki. – swdon

Powiązane problemy