Express next function, do czego tak naprawdę służy?


124

Próbowałem znaleźć dobry opis tego, co next()robi ta metoda. W dokumentacji Express mówi, że next('route')można go użyć do przeskoczenia do tej trasy i pominięcia wszystkich tras pomiędzy nimi, ale czasami nextjest wywoływane bez argumentów. Czy ktoś zna dobry tutorial itp., Który opisuje tę nextfunkcję?

Odpowiedzi:


161

next()bez argumentów mówi „tylko żartuję, nie chcę się tym zajmować”. Wraca i próbuje znaleźć następną pasującą trasę.

Jest to przydatne, powiedzmy, jeśli chcesz mieć jakiegoś rodzaju menedżera stron z informacjami o adresach URL, a także wieloma innymi rzeczami, 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() {
  //...
});

Ten utworzony kod powinien sprawdzać bazę danych pod kątem strony z określonym identyfikatorem. Jeśli znajdzie, wyrenderuj go! jeśli go nie znajdzie, zignoruj ​​tę procedurę obsługi trasy i sprawdź, czy nie ma innych.

Więc next()bez argumentów pozwala udawać, że nie obsłużyłeś trasy, więc zamiast tego może ją odebrać coś innego.


Lub licznik trafień z app.all('*'). Dzięki temu możesz wykonać wspólny kod instalacyjny, a następnie przejść do innych tras, aby zrobić coś bardziej szczegółowego.

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

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

Świetna odpowiedź! Widziałem też inne użycie next, np. Next (err) i next ('route'). Czy teraz masz ich cel, kiedy chcesz propagować błąd, a kiedy chcesz przeskoczyć na określoną trasę?
Andreas Selenwall

8
@AndreasSelenwall next('route')jest specyficzne dla app.VERB()trasy i jest używane, gdy trasa ma wiele wywołań zwrotnych, aby „ ominąć pozostałe wywołania zwrotne trasy.next(err) Jest używany do przeskoczenia do dowolnego „ oprogramowania pośredniczącego błędu ” ( Ez postu).
Jonathan Lonowski

5
Głosowano za. Tylko dla tego wyrażenia: „tylko żartuję, tak naprawdę nie chcę się tym zajmować” sprawiłeś, że zrozumiałem, czego szukam. Widziałem wiele podobnych pytań i znalazłem rozwiązanie w jednym zdaniu.
Pedro Barros

8
Wywołanie next()bez argumentów tak naprawdę nie mówi systemowi "nie chcę tego obsługiwać", po prostu mówi systemowi, aby kontynuował przetwarzanie wszelkich pozostałych programów pośrednich po zakończeniu tego. To nie jest stan błędu do wywołania next(), to część normalnego przepływu. Jeśli nie zadzwonisz, next()żadne inne trasy nie będą w ogóle przetwarzane.
d512

1
Chciałbym, żeby więcej odpowiedzi na tej stronie zostało napisanych dla laika ... 'next () bez argumentów mówi "tylko żartuję, nie chcę się tym zajmować"' - Idealne dla noobów ... (@ d512 ma lepsze wyjaśnienie)
daCoda

129

W większości frameworków otrzymujesz żądanie i chcesz zwrócić odpowiedź. Ze względu na asynchroniczną naturę Node.js napotkasz problemy z zagnieżdżonymi wywołaniami zwrotnymi, jeśli robisz nietrywialne rzeczy. Aby temu zapobiec, Connect.js (przed wersją 4.0 Express.js był warstwą nad connect.js) ma coś, co nazywa się oprogramowaniem pośrednim, czyli funkcją z 2, 3 lub 4 parametrami.

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

Twoja aplikacja Express.js to zestaw tych funkcji.

wprowadź opis obrazu tutaj

Router jest specjalny, jest to oprogramowanie pośredniczące, które umożliwia wykonanie jednego lub więcej oprogramowania pośredniego dla określonego adresu URL. Więc jest to stos wewnątrz stosu.

Więc co dalej? Proste, mówi aplikacji, aby uruchomiła następne oprogramowanie pośredniczące. Ale co się dzieje, gdy przekazujesz coś następnemu? Express przerwie bieżący stos i uruchomi całe oprogramowanie pośredniczące, które ma 4 parametry.

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

To oprogramowanie pośredniczące służy do przetwarzania wszelkich błędów. Lubię:

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

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

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

Jeśli wyobrażasz sobie swoją aplikację Express.js jako stos, prawdopodobnie będziesz w stanie samodzielnie naprawić wiele dziwności. Na przykład, gdy dodajesz oprogramowanie pośredniczące plików cookie po routerze, sensowne jest, aby trasy nie miały plików cookie.


3
Gdzie przechowujesz tę anonimową funkcję logowania?
dennismonsewicz

„Express przerwie bieżący stos i uruchomi całe oprogramowanie pośrednie, które ma 4 parametry”. Zastanawiałem się, w jaki sposób Express jest w stanie uruchomić oprogramowanie pośredniczące do obsługi błędów. Dzięki!
Abhishek Agarwal

75

IMHO, przyjęta odpowiedź na to pytanie nie jest tak naprawdę dokładna. Jak powiedzieli inni, tak naprawdę chodzi o kontrolowanie, kiedy następny handler w łańcuchu zostanie uruchomiony. Ale chciałem podać trochę więcej kodu, aby był bardziej konkretny. Załóżmy, że masz tę prostą aplikację ekspresową:

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 zrobisz

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

zobaczysz to wydrukowane na konsoli:

before request handler
handling request
after request handler

Teraz, jeśli skomentujesz wywołanie next()w środkowym module obsługi w następujący sposób:

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

Zobaczysz to na konsoli:

before request handler
handling request

Zwróć uwagę, że ostatni program obsługi (ten, który drukuje after request handler) nie działa. Dzieje się tak, ponieważ nie mówisz już ekspresowi, aby uruchamiał następny program obsługi.

Więc tak naprawdę nie ma znaczenia, czy "główny" program obsługi (ten, który zwraca 200) powiódł się, czy nie, jeśli chcesz, aby reszta oprogramowania pośredniego działała, musisz zadzwonić next().

Kiedy to się przyda? Załóżmy, że chcesz rejestrować wszystkie żądania, które wpłynęły do ​​jakiejś 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, aby drugi program obsługi działał, musisz wywołać next()pierwszy program obsługi.

Pamiętaj, że węzeł jest asynchroniczny, więc nie może wiedzieć, kiedy zakończyło się wywołanie zwrotne pierwszego programu obsługi. Musisz to powiedzieć dzwoniąc next().


Sonfar to najlepsza odpowiedź dla mnie.
Norayr Ghukasyan

Cóż, wyjaśnienie!
Chang

7

next () bez parametru wywołuje następną procedurę obsługi trasy LUB następne oprogramowanie pośredniczące w środowisku.


2
Albo następne oprogramowanie pośredniczące.
robertklep

1

Oznacza to po prostu przekazanie kontroli następnemu handlerowi.

Twoje zdrowie


1

Zwróć uwagę na powyższe wywołanie metody next (). Wywołanie tej funkcji wywołuje następną funkcję oprogramowania pośredniego w aplikacji. Funkcja next () nie jest częścią Node.js ani Express API, ale jest trzecim argumentem przekazywanym do funkcji oprogramowania pośredniego. Funkcja next () może mieć dowolną nazwę, ale zgodnie z konwencją zawsze nosi nazwę „next”. Aby uniknąć nieporozumień, zawsze używaj tej konwencji.


0

Pytanie zadawane również o wykorzystanie następnej (`` trasy ''), która wydaje się być uwzględniona w dotychczas udzielonych odpowiedziach tydzień:

  1. WYKORZYSTANIE next ():

W skrócie: następna funkcja oprogramowania pośredniego.

Wyciąg z tej oficjalnej dokumentacji Express JS - strona „writing-middleware” :

„Funkcja oprogramowania pośredniego myLogger po prostu drukuje komunikat, a następnie przekazuje żądanie do następnej funkcji oprogramowania pośredniego na stosie, wywołując funkcję next ()”.

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

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)

Ta strona dokumentacji Express JS stwierdza: „Jeśli bieżąca funkcja oprogramowania pośredniego nie kończy cyklu żądanie-odpowiedź, musi wywołać metodę next (), aby przekazać sterowanie do następnej funkcji oprogramowania pośredniego. W przeciwnym razie żądanie pozostanie zawieszone”.

  1. WYKORZYSTANIE next („trasa”):

W skrócie: następna trasa (a następna funkcja oprogramowania pośredniego w przypadku funkcji next ())

Wyciąg z tej dokumentacji Express JS - strona „using-middleware” :

„Aby pominąć pozostałe funkcje oprogramowania pośredniego ze stosu oprogramowania pośredniego routera, wywołaj next („ route ”), aby przekazać kontrolę do następnej trasy . UWAGA: next („ route ”) będzie działać tylko w funkcjach oprogramowania pośredniego, które zostały załadowane przy użyciu app.METHOD () lub router.METHOD ().

Ten przykład przedstawia stos pośredni, który obsługuje żądania GET do ścieżki / user /: id. "

app.get('/user/:id', function (req, res, next) {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, function (req, res, next) {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
  res.render('special')
})

0

next () jest argumentem wywołania zwrotnego funkcji oprogramowania pośredniego z req, a res jest argumentem żądania http i odpowiedzi do next w poniższym kodzie.

app.get ('/', (req, res, next) => {next ()});

Więc next () wywołuje przekazaną funkcję oprogramowania pośredniego. Jeśli bieżąca funkcja oprogramowania pośredniego nie kończy cyklu żądanie-odpowiedź, powinna wywołać metodę next (), w przeciwnym razie żądanie pozostanie zawieszone i przekroczy limit czasu.

Funkcja next () fn musi zostać wywołana w ramach każdej funkcji oprogramowania pośredniego, gdy wiele funkcji oprogramowania pośredniego jest przekazywanych do app.use lub app.METHOD, w przeciwnym razie następna funkcja oprogramowania pośredniego nie zostanie wywołana (w przypadku przekazania więcej niż jednej funkcji oprogramowania pośredniego). Aby pominąć wywoływanie pozostałych funkcji oprogramowania pośredniego, wywołaj next („route”) w ramach funkcji oprogramowania pośredniego, po czym nie należy wywoływać żadnych innych funkcji oprogramowania pośredniego. W poniższym kodzie zostanie wywołane fn1 i fn2, ponieważ next () jest wywoływana w fn1. Jednak fn3 nie zostanie wywołane, ponieważ next („trasa”) jest wywoływana w fn2.

app.get('/fetch', function fn1(req, res, next)  {
console.log("First middleware function called"); 
    next();
}, 
function fn2(req, res, next) {
    console.log("Second middleware function called"); 
    next("route");
}, 
function fn3(req, res, next) {
    console.log("Third middleware function will not be called"); 
    next();
})
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.