Різниця між app.use та app.get у express.js


220

Мені щось нове в express і node.js, і я не можу з’ясувати різницю між app.use та app.get. Схоже, ви можете використовувати їх обох для надсилання інформації. Наприклад:

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

здається, те саме, що це:

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

1
Схоже, ви отримали три різні відповіді, які щось дописували до теми :) Ось відповідне запитання stackoverflow.com/questions/11321635/…
Бенджамін Груенбаум

так, всі хороші відповіді. Спасибі, я погляну на це.
Андре Воробйов

Відповіді:


219

app.use()призначений для прив'язки проміжного програмного забезпечення до вашої програми. Шлях path- це " mount " або " префікс " і обмежує проміжне програмне забезпечення застосовуватися лише до будь-яких запитуваних шляхів, які починаються з нього. Його можна використовувати навіть для вбудовування іншого додатка:

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

// ...

Вказавши /як шлях " mount ", app.use()відповість на будь-який шлях, який починається з /якого є всі вони, і незалежно від використовуваного дієслова HTTP:

  • GET /
  • PUT /foo
  • POST /foo/bar
  • тощо.

app.get(), з іншого боку, є частиною маршрутизації програми Express і призначений для узгодження та обробки конкретного маршруту, коли запитується за допомогою GETдієслова HTTP:

  • GET /

І еквівалентною маршрутизацією для вашого прикладу app.use()насправді буде:

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

( Оновлення: Спроба краще продемонструвати відмінності. )

Методи маршрутизації, в тому числі app.get(), - це зручні методи, які допомагають точніше вирівняти відповіді на запити. Вони також додають у підтримку таких функцій, як параметри та next('route').

Всередині кожного app.get()є заклик до app.use(), тому ви, звичайно, все це можете зробити app.use()безпосередньо. Але це часто вимагає (можливо, зайвого) повторного доповнення різної кількості кодового коду.

Приклади:

  • Для простих, статичних маршрутів:

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

    vs.

    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      // ...
    });
  • З кількома обробниками для одного маршруту:

    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);
    
        // ...
      });
    });
  • З параметрами:

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

Примітка: реалізація Express 'цих функцій містяться в його Router, LayerіRoute .


3
Kudos для згадування вбудованих додатків. Це дуже зручний спосіб організації експрес-програмного забезпечення.
wprl

4
Чи справедливо сказати, що app.use може робити все, що робить кожен app.get, app.post, app.put, але не навпаки?
ngungo

6
ще важко зрозуміти.
Jeb50

1
Добре знати, для чого користуються та отримують користь , але ніхто не робить великої роботи, пояснюючи, як вони функціонують по-різному. З того, що я можу зібрати, усі обробники .use запускаються першими, а .use відповідає будь-якому шляху, який починається із вказаного шляху (тобто .use ('/', ...) та .get ('/ *', ... ) відповідатимуть однаковими шляхами). Мені простіше зрозуміти загальні поняття, коли я можу побачити рухомі частини.
snarf

2
Я думаю, що ПОРЯДО зауваживши, що ця відповідь є застарілою і застарілою, на дату мого коментаря вам більше нічого і не потрібно, path-to-regexpі ви можете використовувати параметри маршруту безпосередньо в першому аргументі useметоду.
вдегенне

50

app.use є методом "нижчого рівня" від Connect, середнього програмного забезпечення, від якого залежить Express.

Ось мій принцип:

  • Використовуйте app.get якщо ви хочете викрити метод GET.
  • Використовуйте, app.useякщо ви хочете додати деяке посередництво (обробник для HTTP-запиту до того, як він прибуде до маршрутів, які ви встановили в Express), або якщо ви хочете зробити свої маршрути модульними (наприклад, виставити набір маршрутів від модуля npm, який можуть використовувати інші веб-програми).

Але якщо я не дбаю про метод, я можу використовувати app.useдля обробки деяких маршрутів? Або ми ніколи не повинні використовувати app.useдля маршрутизації.
Елементо0

Ви можете використовувати app.use для переміщення маршрутів для відокремлення файлів екв. users.js, building.js
Роб Анжельє

1
хоча одна відповідь вище цього зібрала набагато більше ВПРОВАДЖЕННЯ / ЗГОДИ, ваша відповідь перекладає складну річ, включаючи проміжне програмне забезпечення, в кілька простих слів, кудо.
Jeb50

50

Просте app.use означає "Запустити це на ВСІХ запитах"
app.get означає "Запустити це на GET-запит для вказаної URL-адреси"


Це не так просто. Прочитайте інші відповіді.
Девід Лопес

28

app.getвикликається , коли метод HTTP встановлений на GET, в той час як app.useназивається незалежно від методу HTTP, і , отже , визначає шар , який знаходиться на вершині всіх інших типів , які RESTful експрес - пакети дає вам доступ к.


19

Різниця між app.use&app.get :

app.use → Зазвичай використовується для введення середніх програм у вашу програму і може обробляти всі типи HTTP-запитів.

app.get → Це лише для обробки GET HTTP-запитів.

Тепер виникає плутанина між app.use& app.all. Без сумніву, є одне спільне в них, що обидва можуть обробляти всі типи HTTP-запитів. Але є деякі відмінності, які рекомендують нам використовувати app.use для середнього рівня та app.all для обробки маршруту.

  1. app.use()→ Потрібен лише один зворотний дзвінок.
    app.all()→ Це може приймати кілька зворотних дзвінків.

  2. app.use()побачить лише, чи починається URL із вказаного шляху.
    Але, app.all()буде відповідати цілому шляху.

Наприклад,

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()дзвонити всередині app.use()буде викликати або наступний проміжне програмне забезпечення або будь-який обробник маршруту, але next()всередині виклику app.all()буде викликати наступний оброблювач маршруту ( app.all(), і app.get/post/put...т.д.) тільки. Якщо після цього є якесь проміжне програмне забезпечення, воно буде пропущено. Отже, бажано розміщувати всі проміжні продукти завжди над обробниками маршрутів.

1
Ваша точка 3, мабуть, не застосовується до Express 4.16. закликаючи next()всередину app.all('/*', ...)волі, насправді виконується app.use('/', ...)пізніше у файлі. Можливо, я вас там неправильно зрозумів. Дуже корисне пояснення інакше.
BeetleJuice

У 4.17 я спостерігав те саме, що і @BeetleJuice
Девід Лопес

4

На додаток до вищезазначених пояснень, що я відчуваю:

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

відповідатиме всім запитам, починаючи з "/ book" як URL. тому він також відповідає "/ книга / 1" або "/ книга / 2"

app.get('/book')  

відповідає лише GET запиту з точною відповідністю . Він не буде обробляти такі URL-адреси, як "/ книга / 1" або "/ книга / 2"

Отже, якщо ви хочете глобальний обробник, який обробляє всі ваші маршрути, то app.use('/')це варіант. app.get('/')буде обробляти лише кореневу URL-адресу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.