Różnica między app.all ('*') a app.use ('/')

121

Czy istnieje użyteczna różnica między app.all('*', ... )i app.use('/', ...)w Node.JS Express?

ostergaard
źródło

Odpowiedzi:

119

W większości przypadków działałyby równoważnie. Największą różnicą jest kolejność, w jakiej zostanie zastosowane oprogramowanie pośredniczące:

  • app.all() przyłącza się do routera aplikacji, więc jest używane za każdym razem, gdy zostanie osiągnięte oprogramowanie pośredniczące app.router (które obsługuje wszystkie trasy metod ... GET, POST itp.).

UWAGA: app.router stał się przestarzały w express 4.x

  • app.use()dołącza się do głównego stosu oprogramowania pośredniego aplikacji, więc jest używany w kolejności określonej przez oprogramowanie pośredniczące. np. jeśli umieścisz go jako pierwszy, będzie to pierwsza rzecz do uruchomienia. Jeśli umieścisz go na końcu (za routerem), zwykle w ogóle nie będzie działać.

Zwykle, jeśli chcesz zrobić coś globalnie dla wszystkich tras, lepszym rozwiązaniem jest app.use (). Ponadto ma mniejsze szanse na przyszłe błędy, ponieważ express 0.4 prawdopodobnie porzuci niejawny router (co oznacza, że ​​pozycja routera w oprogramowaniu pośrednim będzie ważniejsza niż teraz, ponieważ technicznie nie musisz go nawet używać teraz).

hunterloftis
źródło
15
Czy to nadal obowiązuje po Express 4.x? app.router został usunięty.
ruffrey
1
Możesz używać next("route")with app.all, ale nie with app.use.
Jozef Mikušinec
@JozefMikusinec Dokumentacja wydaje się sugerować inaczej ... expressjs.com/en/guide/writing-middleware.html
musicin3d
Twój link nie wspomina dalej („trasa”), ale spojrzałem na API, masz rację.
Jozef Mikušinec
2
@ musicin3d Poszukałem dalej i znalazłem ten problem z GitHubem , który potwierdza, że ​​"next () i next ('route') nie mają różnicy w app.use" (quote). Powinni zmienić dokumenty.
Jozef Mikušinec
87

app.use przyjmuje tylko jedną funkcję zwrotną i jest przeznaczona dla oprogramowania pośredniczącego. Oprogramowanie pośredniczące zwykle nie obsługuje żądań i odpowiedzi (technicznie jest to możliwe), po prostu przetwarza dane wejściowe i przekazuje je do następnego programu obsługi w kolejce.

app.use([path], function)

app.all przyjmuje wiele wywołań zwrotnych i jest przeznaczony do routingu. dzięki wielu callbackom możesz filtrować zapytania i wysyłać odpowiedzi. Jest to wyjaśnione w sekcji Filtry na express.js

app.all(path, [callback...], callback)

app.use widzi tylko, czy adres URL zaczyna się od określonej ścieżki

app.use( "/product" , mymiddleware);
// will match /product
// will match /product/cool
// will match /product/foo

app.all dopasuje pełną ścieżkę

app.all( "/product" , handler);
// will match /product
// won't match /product/cool   <-- important
// won't match /product/foo    <-- important

app.all( "/product/*" , handler);
// won't match /product        <-- Important
// will match /product/
// will match /product/cool
// will match /product/foo
Palani
źródło
17
Przynajmniej w wersji 4, app.use przyjmuje jedną lub więcej funkcji oprogramowania pośredniego, a nie „tylko jedną”.
Jess Austin
2
app.use sprawdza tylko, czy adres URL zaczyna się od określonej ścieżki; app.all będzie pasować do pełnej ścieżki. to jest główna różnica.
meizilp
@frogcjn nie, nie powinno, ponieważ ignoruje * i / w moim pytaniu.
ostergaard
15
  • app.use:

    1. wstrzyknij oprogramowanie pośrednie do kontrolera frontowego, konfigurując na przykład: nagłówek, pliki cookie, sesje itp.
    2. musi być napisane przed aplikacją [http_method], w przeciwnym razie nie zostanie wykonana.
    3. kilka połączeń jest przetwarzanych w kolejności pisania
  • app.all:

    1. (podobnie jak aplikacja [http_method]) służy do konfigurowania kontrolerów tras
    2. „wszystkie” oznacza, że ​​ma zastosowanie do wszystkich metod http.
    3. kilka połączeń jest przetwarzanych w kolejności pisania

Spójrz na ten przykład kodu expressJs:

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

app.use(function frontControllerMiddlewareExecuted(req, res, next){
  console.log('(1) this frontControllerMiddlewareExecuted is executed');
  next();
});

app.all('*', function(req, res, next){
  console.log('(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next');
  next();
});

app.all('/hello', function(req, res, next){
  console.log('(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next');
  next();
});

app.use(function frontControllerMiddlewareNotExecuted(req, res, next){
  console.log('(4) this frontControllerMiddlewareNotExecuted is not executed');
  next();
});

app.get('/hello', function(req, res){
  console.log('(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response');
  res.send('Hello World');
});

app.listen(80);

Oto dziennik uzyskiwania dostępu do trasy „/ hello”:

(1) this frontControllerMiddlewareExecuted is executed
(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next
(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next
(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response
daemon1981
źródło
6
Po uruchomieniu tego przykładu dosłownie w programie Express 4.x faktycznie uruchamia wszystkie 5 w kolejności. Jest to prawdopodobnie spowodowane zmianami w ekspresie w ciągu prawie 3 lat od czasu napisania tego tekstu, ale pomyślałem, że dodam to dla jasności.
Nathan Wiebe,
11

W app.use()przypadku ścieżki „montowania” jest usuwana i nie jest widoczna dla funkcji oprogramowania pośredniego:

app.use('/static', express.static(__dirname + '/public'));

Zamontowane funkcje oprogramowania pośredniego ( express.static) nie są wywoływane, chyba że element req.urlzawiera ten prefiks ( /static), w którym to momencie jest usuwany, gdy funkcja jest wywoływana.

Dzięki app.all(), że nie ma to zachowanie.

lepiej 9
źródło
Pytanie dotyczy tylko app.use („/”, ...).
ostergaard
To poprawna odpowiedź na pytanie, które w 2018 roku jest nadal aktualne! Oprogramowanie pośredniczące można również zamontować za pomocą funkcji all () ... jedyną różnicą jest to, że ścieżka montowania jest usuwana podczas wykonywania oprogramowania pośredniego.
Xatian
4

Tak, app.all()jest wywoływana, gdy żądany jest określony identyfikator URI za pomocą dowolnego typu metody żądania (POST, GET, PUT lub DELETE)

Z drugiej strony app.use()jest używany dla dowolnego oprogramowania pośredniego, które możesz mieć, i jest montowany na prefiksie ścieżki i będzie wywoływany za każdym razem, gdy zażąda się identyfikatora URI w ramach tej trasy.

Oto dokumentacja dotycząca app.all i app.use .

Gurpreet Singh
źródło
dzięki, ale myślę, że przegapiłeś app.all wildcard i app.use root path, które sprawiają, że są dokładnie takie same, prawda? Poza tym, że app.all może przyjmować szereg wywołań zwrotnych, a app.use może przyjmować tylko jedno - prawda?
ostergaard
1

Dwie różnice we wszystkich powyższych odpowiedziach nie są spełnione.

Pierwsza: app.allakceptuje wyrażenie regularne jako parametr ścieżki. app.useNIE akceptuje wyrażenia regularnego.

Drugi: app.all(path,handler)lub app[method](path,handler), przewodnik pathmusi być taki sam dla wszystkich path . Oznacza to, że ścieżka aplikacji [metoda] ”jest kompletna.

app.use(path,hanlder), jeśli ścieżka użycia jest kompletna, ścieżka hanldera musi mieć postać „/”. jeśli ścieżka użycia jest początkiem pełnej ścieżki, ścieżka obsługi musi być resztą całej ścieżki.

 app.use('/users', users);

  //users.js:  the handler will be called when matchs `/user/` path
      router.get('/', function(req, res, next) {
      res.send('respond with a resource');
    });
  // others.js: the handler will be called when matchs `/users/users` path
      router.get('/users', function(req, res, next) {
      res.send('respond with a resource');
    });

app.all('/users', users);

//others.js: the handler wil be called when matchs `/`path
router.get('/', function(req, res, next) {
     res.send('respond with a resource');
});
//users.js: the handler will be called when matchs `/users` path
router.get('/users', function(req, res, next) {
    res.send('respond with a resource');
 });
JackChouMine
źródło
0

Istnieją dwie główne różnice:

1. dopasowanie wzorców (odpowiedź udzielona przez Palaniego)
2. next(route)nie będzie działać wewnątrz treści funkcji oprogramowania pośredniego załadowanego za pomocą app.use. Jest to określone w linku z dokumentów:

NOTE: next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.

Link: http://expressjs.com/en/guide/using-middleware.html

Efekt pracy next('route')można zobaczyć na poniższym przykładzie:

app.get('/',
(req,res,next)=>{console.log("1");
next(route); //The code here skips ALL the following middlewares
}
(req,res,next)=>{next();}, //skipped
(req,res,next)=>{next();}  //skipped
);

//Not skipped
app.get('/',function(req,res,next){console.log("2");next();});
Ng Ju Ping
źródło