Differenza tra app.use e app.get in express.js


224

Sono un po 'nuovo per express e node.js e non riesco a capire la differenza tra app.use e app.get. Sembra che tu possa usarli entrambi per inviare informazioni. Per esempio:

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

sembra essere lo stesso di questo:

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

1
Sembra che tu abbia ottenuto tre risposte diverse, tutte che contribuiscono in qualche modo all'argomento :) Ecco una domanda correlata stackoverflow.com/questions/11321635/…
Benjamin Gruenbaum

sì, tutte buone risposte. Grazie, ci penso io.
Andre Vorobyov

Risposte:


225

app.use()è concepito per associare il middleware all'applicazione. Il pathè un " mount oppure" " prefisso di percorso" e limita il middleware di applicare solo per i percorsi chiesto che iniziano con esso. Può anche essere utilizzato per incorporare un'altra applicazione:

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

// ...

Specificando /come percorso " mount ", app.use()risponderà a qualsiasi percorso che inizi con /, che sono tutti e indipendentemente dal verbo HTTP utilizzato:

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

app.get(), d'altra parte, fa parte del routing dell'applicazione di Express ed è inteso per abbinare e gestire un percorso specifico quando richiesto con il GETverbo HTTP:

  • GET /

E il routing equivalente per il tuo esempio di app.use()sarebbe effettivamente:

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

( Aggiornamento: tentativo di dimostrare meglio le differenze. )

I metodi di instradamento, inclusi app.get(), sono metodi convenienti che consentono di allineare le risposte alle richieste in modo più preciso. Aggiungono anche il supporto per funzionalità come parametri e next('route').

All'interno di ciascuna app.get()c'è una chiamata a app.use(), quindi puoi certamente fare tutto questo app.use()direttamente. Ma farlo spesso richiederà (probabilmente inutilmente) la reimplementazione di varie quantità di codice boilerplate.

Esempi:

  • Per percorsi semplici e statici:

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

    vs.

    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      // ...
    });
    
  • Con più gestori per lo stesso percorso:

    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);
    
        // ...
      });
    });
    
  • Con parametri:

    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;
      // ...
    });
    

Nota: implementazione Express' di queste caratteristiche sono contenute nella sua Router, LayereRoute .


4
Complimenti per aver menzionato le app incorporate. È un modo molto pratico per organizzare il middleware espresso.
wprl

4
È giusto dire che app.use può fare tutto ciò che ognuno di app.get, app.post, app.put fa ma non viceversa?
ngungo

6
ancora difficile da capire.
Jeb50

1
E 'bene sapere che cosa uso e ottenere sono per , ma nessuno fa un grande lavoro di spiegare come funzionano in modo diverso. Da quello che posso raccogliere, tutti i gestori .use vengono eseguiti per primi e .use corrisponde a qualsiasi percorso che inizia con il percorso specificato (ad esempio .use ('/', ...) e .get ('/ *', ... ) corrisponderebbe agli stessi percorsi). Per me è più facile capire i concetti generali quando posso vedere le parti in movimento.
Snarf

3
Penso che valga la pena NOTARE che questa risposta è vecchia e obsoleta, alla data del mio commento non hai più bisogno path-to-regexpo altro e puoi usare i parametri del percorso direttamente nel primo argomento del usemetodo.
vdegenne

52

app.use è il metodo di "livello inferiore" di Connect, il framework middleware da cui dipende Express.

Ecco la mia linea guida:

  • Usa app.getse vuoi esporre un metodo GET.
  • Da utilizzare app.usese desideri aggiungere del middleware (un gestore per la richiesta HTTP prima che arrivi alle rotte che hai impostato in Express) o se desideri rendere modulari le tue rotte (ad esempio, esporre un insieme di rotte da un modulo npm che altre applicazioni web potrebbero utilizzare).

1
Ma se non mi interessa il metodo, posso usarlo app.useper gestire alcuni percorsi? Oppure non dovremmo mai usare app.useper il routing.
Elemento0

1
Puoi usare app.use per spostare i tuoi percorsi su file separati eq. users.js, buildings.js
Rob Angelier,

2
sebbene la risposta sopra questa abbia raccolto molto di più SU / ACCETTO, la tua risposta traduce cose sofisticate, incluso il middleware, in poche semplici parole, kudo.
Jeb50

50

Semplicemente app.use significa "Esegui su TUTTE le richieste"
app.get significa "Esegui su una richiesta GET, per l'URL specificato"


Non è così semplice. Leggi altre risposte.
David Lopez

28

app.getviene chiamato quando il metodo HTTP è impostato su GET, mentre app.useviene chiamato indipendentemente dal metodo HTTP, e quindi definisce un livello che si trova in cima a tutti gli altri tipi RESTful a cui i pacchetti express ti danno accesso.


22

Differenza tra app.use& app.get:

app.use → Viene generalmente utilizzato per introdurre middleware nell'applicazione e può gestire tutti i tipi di richieste HTTP.

app.get → Serve solo per la gestione delle richieste GET HTTP.

Ora, c'è una confusione tra app.use& app.all. Senza dubbio, c'è una cosa comune in loro, che entrambi possono gestire tutti i tipi di richieste HTTP. Ma ci sono alcune differenze che ci consigliano di usare app.use per i middleware e app.all per la gestione del percorso.

  1. app.use()→ È necessaria una sola richiamata.
    app.all()→ Può richiedere più richiamate.

  2. app.use()vedrà solo se l'URL inizia con il percorso specificato.
    Ma app.all()corrisponderà al percorso completo.

Per esempio,

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()call inside app.use()chiamerà il middleware successivo o qualsiasi gestore di route, ma next()call inside app.all()richiamerà solo il gestore di route successivo ( app.all(), app.get/post/put...ecc.). Se è presente del middleware dopo, verrà ignorato. Quindi, è consigliabile mettere tutti i middleware sempre sopra i gestori di rotta.

1
Il tuo punto 3 non sembra applicarsi a Express 4.16. la chiamata next()all'interno di app.all('/*', ...)verrà infatti eseguita in un app.use('/', ...)secondo momento nel file. Forse ti ho frainteso lì. Spiegazione molto utile altrimenti.
BeetleJuice

1
In 4.17 ho osservato lo stesso di @BeetleJuice
David Lopez il

6

Oltre alle spiegazioni di cui sopra, quello che provo:

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

corrisponderà a tutte le richieste che iniziano con "/ book" come URL. quindi corrisponde anche a "/ book / 1" o "/ book / 2"

app.get('/book')  

corrisponde solo alla richiesta GET con corrispondenza esatta . Non gestirà URL come "/ book / 1" o "/ book / 2"

Quindi, se vuoi un gestore globale che gestisca tutte le tue rotte, allora app.use('/')è l'opzione. app.get('/')gestirà solo l'URL di root.


1

Ci sono 3 differenze principali che ho riscontrato fino ad ora. Il terzo non è così ovvio e potresti trovarlo interessante. Le differenze sono le stesse per l'espresso router. Ciò significa router.use()e router.get()o di altro post, put, allmetodi, ecc ha anche stessa differenza.

1

  • app.use(path, callback) risponderà a qualsiasi richiesta HTTP.
  • app.get(path, callback)risponderà solo alla GETrichiesta HTTP. Allo stesso modo, post, put, ecc risponderà alla loro richiesta corrispondente. app.all()risponde a qualsiasi richiesta HTTP così app.use()e app.all()sono gli stessi in questa parte.

2

  • app.use(path, callback)corrisponderà al prefisso del percorso della richiesta e risponde se un qualsiasi prefisso del percorso della richiesta corrisponde al parametro del percorso. Ad esempio se il parametro path è "/", allora sarà corrispondenti "/", "/about", "/users/123"etc.
  • app.get(path, callback)Qui get corrisponderà all'intero percorso. Lo stesso per altre richieste HTTP e app.all(). Ad esempio, se il parametro path è "/", allora corrisponderà solo "/".

3

next('route') non funziona sulle funzioni middleware / callback di app.use(). Funziona solo su app.get(), app.all()e l'altra funzione analoga di altre richieste HTTP.

Secondo la documentazione espressa :

next ('route') funzionerà solo nelle funzioni middleware che sono state caricate utilizzando le funzioni app.METHOD () o router.METHOD ().

METHOD è il metodo HTTP della richiesta che la funzione middleware gestisce (come GET, PUT o POST) in lettere minuscole.

Da qui useremo la parola chiave METODO invece get, post, all, ecc
Ma che cosa è next('route')?!

Vediamo.

successivo ('route')

vediamo, app.use()o app.METHOD()può richiedere diverse funzioni di callback / middleware.

Dalla documentazione espressa :

Le funzioni middleware sono funzioni che hanno accesso all'oggetto richiesta (req), all'oggetto risposta (res) e alla successiva funzione middleware nel ciclo richiesta-risposta dell'applicazione. La successiva funzione middleware è comunemente indicata da una variabile denominata next.

Se la funzione middleware corrente non termina il ciclo richiesta-risposta, deve chiamare next () per passare il controllo alla funzione middleware successiva. In caso contrario, la richiesta verrà lasciata in sospeso.

Quindi vediamo che ogni funzione middleware deve chiamare la successiva funzione middleware o terminare la risposta. E questo è lo stesso per app.use()e app.METHOD().

Ma a volte, in alcune condizioni, potresti voler saltare tutte le successive funzioni di callback per la rotta corrente ma anche non voler terminare la risposta adesso. Perché forse ci sono altri percorsi che dovrebbero essere abbinati. Quindi, per saltare tutte le funzioni di callback del percorso corrente senza terminare la risposta, puoi eseguire next('route'). Salterà tutte le funzioni di richiamata della rotta corrente e cercherà di abbinare le rotte successive.

Ad esempio (dalla documentazione espressa ):

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) {
  // send a regular response
  res.send('regular')
})

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

Vedi, qui in una certa condizione (req.params.id === '0')vogliamo saltare la prossima funzione di callback ma non vogliamo nemmeno terminare la risposta perché c'è un'altra rotta dello stesso parametro di percorso che verrà abbinata e quella rotta invierà una risposta speciale. (Sì, è valido utilizzare lo stesso parametro di percorso per lo stesso METHODpiù volte. In questi casi, tutte le rotte verranno abbinate fino al termine della risposta). Quindi, in questi casi, eseguiamo il next('route')e tutta la funzione di callback della rotta corrente viene saltata. Qui se la condizione non è soddisfatta, chiamiamo la successiva funzione di callback.

Questo next('route')comportamento è possibile solo nelle app.METHOD()funzioni.

Richiamando dalla documentazione espressa :

next ('route') funzionerà solo nelle funzioni middleware che sono state caricate utilizzando le funzioni app.METHOD () o router.METHOD ().

Poiché non è possibile saltare tutte le funzioni di callback della rotta corrente in app.use(), dovremmo stare attenti qui. Dovremmo usare solo le funzioni middleware in app.use()cui non è necessario saltare in nessuna condizione. Poiché dobbiamo terminare la risposta o attraversare tutte le funzioni di callback dall'inizio alla fine, non possiamo saltarle affatto.

Puoi visitare qui per ulteriori informazioni

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.