Różnica między app.use i app.get w express.js

220

Jestem trochę nowy do wyrażenia i node.js i nie mogę zrozumieć różnicy między app.use i app.get. Wygląda na to, że możesz użyć obu z nich do wysyłania informacji. Na przykład:

app.use('/',function(req, res,next) {
    res.send('Hello');
    next();
});

wydaje się być taki sam:

app.get('/', function (req,res) {
   res.send('Hello');
});
Andre Vorobyov
źródło
1
Wygląda na to, że masz trzy różne odpowiedzi, z których wszystkie przyczyniają się do tematu :) Oto powiązane pytanie stackoverflow.com/questions/11321635/...
Benjamin Gruenbaum
tak, wszystkie dobre odpowiedzi. Dzięki, spojrzę na to.
Andre Vorobyov

Odpowiedzi:

219

app.use()jest przeznaczony do wiązania oprogramowania pośredniego z aplikacją. Jest pathto ścieżka „ montowania ” lub „ prefiksu ” i ogranicza oprogramowanie pośrednie do stosowania tylko do żądanych ścieżek, które zaczynają się od niego. Można go nawet użyć do osadzenia innej aplikacji:

// subapp.js
var express = require('express');
var app = modules.exports = express();
// ...
// server.js
var express = require('express');
var app = express();

app.use('/subapp', require('./subapp'));

// ...

Określając /jako ścieżkę „ mount ”, app.use()odpowie na każdą ścieżkę, która zaczyna się od /, które są wszystkie i niezależnie od użytego czasownika HTTP:

  • GET /
  • PUT /foo
  • POST /foo/bar
  • itp.

app.get(), z drugiej strony, jest częścią routingu aplikacji Express i jest przeznaczony do dopasowywania i obsługi określonej trasy na żądanie GETczasownika HTTP:

  • GET /

Odpowiednim routingiem dla Twojego przykładu app.use()byłoby:

app.all(/^\/.*/, function (req, res) {
    res.send('Hello');
});

( Aktualizacja: Próba lepszego wykazania różnic. )

Metody routingu, w tym app.get(), są wygodnymi metodami, które pomagają precyzyjniej dopasowywać odpowiedzi na żądania. Dodają także obsługę takich funkcji, jak parametry i next('route').

Wewnątrz każdego app.get()jest wezwanie do app.use(), więc z pewnością możesz to wszystko zrobić app.use()bezpośrednio. Ale zrobienie tego często będzie wymagało (prawdopodobnie niepotrzebnie) zaimplementowania różnych ilości kodu płyty głównej.

Przykłady:

  • W przypadku prostych, statycznych tras:

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

    vs.

    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      // ...
    });
  • Z wieloma modułami obsługi dla tej samej trasy:

    app.get('/', authorize('ADMIN'), function (req, res) {
      // ...
    });

    vs.

    const authorizeAdmin = authorize('ADMIN');
    
    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      authorizeAdmin(req, res, function (err) {
        if (err) return next(err);
    
        // ...
      });
    });
  • Z parametrami:

    app.get('/item/:id', function (req, res) {
      let id = req.params.id;
      // ...
    });

    vs.

    const pathToRegExp = require('path-to-regexp');
    
    function prepareParams(matches, pathKeys, previousParams) {
      var params = previousParams || {};
    
      // TODO: support repeating keys...
      matches.slice(1).forEach(function (segment, index) {
        let { name } = pathKeys[index];
        params[name] = segment;
      });
    
      return params;
    }
    
    const itemIdKeys = [];
    const itemIdPattern = pathToRegExp('/item/:id', itemIdKeys);
    
    app.use('/', function (req, res, next) {
      if (req.method !== 'GET') return next();
    
      var urlMatch = itemIdPattern.exec(req.url);
      if (!urlMatch) return next();
    
      if (itemIdKeys && itemIdKeys.length)
        req.params = prepareParams(urlMatch, itemIdKeys, req.params);
    
      let id = req.params.id;
      // ...
    });

Uwaga: wdrożenie Express' z tych funkcji są zawarte w jego Router, LayeriRoute .

Jonathan Lonowski
źródło
3
Wyrazy uznania za wspomnienie o aplikacjach osadzonych. Jest to bardzo przydatny sposób organizowania ekspresowego oprogramowania pośredniego.
wprl
4
Czy można powiedzieć, że app.use może zrobić wszystko z app.get, app.post, app.put, ale nie odwrotnie?
ngungo
6
wciąż trudny do zrozumienia.
Jeb50
1
Dobrze jest wiedzieć, po co i dostać się do , ale nikt nie robi świetną robotę, wyjaśniając, w jaki sposób działać w różny sposób. Z tego, co mogę zebrać, wszystkie programy obsługi .use uruchamiane są jako pierwsze, a .use pasuje do dowolnej ścieżki, która zaczyna się od określonej ścieżki (tj. .Use ('/', ...) i .get ('/ *', ... ) pasują do tych samych ścieżek). Dla mnie łatwiej jest zrozumieć ogólne koncepcje, kiedy widzę ruchome części.
snarf
2
Myślę, że WARTO ZWRÓCIĆ UWAGĘ, że ta odpowiedź jest stara i nieaktualna, ponieważ na dzień mojego komentarza już nie potrzebujesz path-to-regexpani nic i możesz użyć parametrów trasy bezpośrednio w pierwszym argumencie usemetody.
vdegenne
50

app.use jest metodą „niższego poziomu” firmy Connect, frameworka oprogramowania pośredniego, od którego zależy Express.

Oto moja wskazówka:

  • Użyj, app.getjeśli chcesz ujawnić metodę GET.
  • Użyj, app.usejeśli chcesz dodać oprogramowanie pośrednie (moduł obsługi żądania HTTP, zanim dotrze ono do tras skonfigurowanych w Express) lub jeśli chcesz, aby Twoje trasy były modułowe (na przykład ujawnij zestaw tras z modułu npm, z którego mogłyby korzystać inne aplikacje internetowe).
Matthew Ratzloff
źródło
Ale jeśli nie obchodzi mnie metoda, mogę użyć app.useniektórych tras? Lub nigdy nie powinniśmy używać app.usedo routingu.
Elemento0,
Możesz użyć app.use, aby przenieść swoje trasy do oddzielnych plików eq. users.js, buildings.js
Rob Angelier
1
chociaż jedna z powyższych odpowiedzi zebrała więcej UP / AGREE, twoja odpowiedź przekłada wyrafinowaną rzecz, w tym Middleware, na kilka prostych słów, kudo.
Jeb50
50

Po prostu app.use oznacza „Uruchom to na WSZYSTKICH żądaniach”
app.get oznacza „Uruchom to na żądanie GET dla danego adresu URL”

Dhyan Mohandas
źródło
To nie takie proste. Przeczytaj inne odpowiedzi.
David Lopez
28

app.getjest wywoływany, gdy metoda HTTP jest ustawiona na GET, natomiast app.usejest wywoływana niezależnie od metody HTTP, a zatem definiuje warstwę, która jest na wierzchu wszystkich innych typów RESTful, do których dostęp mają pakiety ekspresowe.

MrLore
źródło
19

Różnica między app.use& app.get:

app.use → Zasadniczo służy do wprowadzania oprogramowania pośredniego w aplikacji i może obsługiwać wszystkie typy żądań HTTP.

app.get → Służy tylko do obsługi żądań GET HTTP.

Teraz istnieje pomieszanie między app.use& app.all. Bez wątpienia jest w nich jedna wspólna cecha: obie mogą obsługiwać wszelkiego rodzaju żądania HTTP. Ale istnieją pewne różnice, które zalecają nam używanie app.use do oprogramowania pośredniego i app.all do obsługi tras.

  1. app.use()→ Zajmuje tylko jedno oddzwonienie.
    app.all()→ Może to obejmować wiele połączeń zwrotnych.

  2. app.use()zobaczy tylko, czy adres URL zaczyna się od określonej ścieżki.
    Ale app.all()dopasuje pełną ścieżkę.

Na przykład,

app.use( "/book" , middleware);
// will match /book
// will match /book/author
// will match /book/subject

app.all( "/book" , handler);
// will match /book
// won't match /book/author   
// won't match /book/subject    

app.all( "/book/*" , handler);
// won't match /book        
// will match /book/author
// will match /book/subject
  1. next()zadzwoń wewnątrz app.use()zadzwoni albo kolejnej warstwy pośredniej ani żadnej obsługi trasy, ale next()rozmowa wewnątrz app.all()wywoła kolejną obsługi trasy ( app.all(), app.get/post/put...etc.) tylko. Jeśli pojawi się jakieś oprogramowanie pośrednie, zostanie ono pominięte. Dlatego wskazane jest, aby umieścić wszystkie oprogramowanie pośrednie zawsze powyżej procedur obsługi trasy.
Ankit Kumar
źródło
1
Twój punkt 3 wydaje się nie mieć zastosowania do Express 4.16. wywołanie next()wewnątrz app.all('/*', ...)spowoduje wykonanie app.use('/', ...)później w pliku. Może źle cię tam zrozumiałem. Bardzo pomocne wyjaśnienie inaczej.
BeetleJuice
W 4.17 zaobserwowałem to samo, co @BeetleJuice
David Lopez
4

Oprócz powyższych wyjaśnień, czego doświadczam:

app.use('/book', handler);  

dopasuje wszystkie żądania zaczynające się od „/ book” jako URL. więc pasuje również do „/ book / 1” lub „/ book / 2”

app.get('/book')  

dopasowuje tylko żądanie GET z dopasowaniem ścisłym . Nie obsługuje adresów URL takich jak „/ book / 1” lub „/ book / 2”

Tak więc, jeśli chcesz mieć globalny moduł obsługi, który obsługuje wszystkie twoje trasy, app.use('/')jest to opcja. app.get('/')obsłuży tylko główny adres URL.

Atilla Baspinar
źródło