Sự khác biệt giữa app.use và app.get trong express.js


220

Tôi là người mới để thể hiện và node.js và tôi không thể tìm ra sự khác biệt giữa app.use và app.get. Có vẻ như bạn có thể sử dụng cả hai để gửi thông tin. Ví dụ:

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

dường như giống như thế này:

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

1
Có vẻ như bạn đã nhận được ba câu trả lời khác nhau, tất cả đều đóng góp một cái gì đó cho chủ đề này :) Đây là một câu hỏi liên quan stackoverflow.com/questions/11321635/
mẹo

vâng, tất cả các câu trả lời tốt. Cảm ơn, tôi sẽ xem xét điều đó.
Andre Vorobyov

Câu trả lời:


219

app.use()được thiết kế để ràng buộc phần mềm trung gian với ứng dụng của bạn. Đây pathlà đường dẫn " mount " hoặc " prefix " và giới hạn phần mềm trung gian chỉ áp dụng cho bất kỳ đường dẫn nào được yêu cầu bắt đầu với nó. Nó thậm chí có thể được sử dụng để nhúng một ứng dụng khác:

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

// ...

Bằng cách chỉ định /là đường dẫn " gắn kết ", app.use()sẽ phản hồi bất kỳ đường dẫn nào bắt đầu bằng /tất cả chúng và bất kể động từ HTTP được sử dụng:

  • GET /
  • PUT /foo
  • POST /foo/bar
  • Vân vân.

app.get()mặt khác, là một phần của định tuyến ứng dụng của Express và được dùng để khớp và xử lý một tuyến cụ thể khi được yêu cầu với GETđộng từ HTTP:

  • GET /

Và, định tuyến tương đương cho ví dụ của bạn app.use()thực sự sẽ là:

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

( Cập nhật: Cố gắng thể hiện tốt hơn sự khác biệt. )

Các phương thức định tuyến, bao gồm app.get(), là các phương thức tiện lợi giúp bạn căn chỉnh các phản hồi cho các yêu cầu chính xác hơn. Họ cũng thêm hỗ trợ cho các tính năng như tham sốnext('route').

Trong mỗi app.get()cuộc gọi là một cuộc gọi đến app.use(), vì vậy bạn chắc chắn có thể thực hiện tất cả điều này với app.use()trực tiếp. Nhưng, làm như vậy thường sẽ yêu cầu (có thể không cần thiết) thực hiện lại số lượng mã soạn sẵn khác nhau.

Ví dụ:

  • Đối với các tuyến đường đơn giản, tĩnh:

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

    so với

    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      // ...
    });
  • Với nhiều trình xử lý cho cùng một tuyến đường:

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

    so với

    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);
    
        // ...
      });
    });
  • Với các tham số:

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

    so với

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

Lưu ý: việc thực hiện các tính năng Express được chứa trong nó Router, LayerRoute .


3
Kudos để đề cập đến các ứng dụng nhúng. Đó là một cách rất thuận tiện để tổ chức phần mềm trung gian cấp tốc.
wprl

4
Có công bằng không khi nói rằng app.use có thể làm mọi thứ trong mỗi app.get, app.post, app.put không nhưng ngược lại?
ngungo

6
vẫn khó hiểu.
Jeb50

1
Thật tốt khi biết sử dụng và nhận được để làm gì , nhưng không ai làm tốt công việc giải thích cách chúng hoạt động khác nhau. Từ những gì tôi có thể thu thập, tất cả các trình xử lý .use chạy trước và .use khớp với bất kỳ đường dẫn nào bắt đầu bằng đường dẫn đã chỉ định (ví dụ: use ('/', ...) và .get ('/ *', ... ) sẽ phù hợp với các đường dẫn tương tự). Đối với tôi, việc hiểu các khái niệm tổng thể dễ dàng hơn khi tôi có thể thấy các bộ phận chuyển động.
snarf 18/03/18

2
Tôi nghĩ rằng KHÔNG THỂ NÀO rằng phản hồi này đã cũ và lỗi thời, kể từ ngày nhận xét của tôi bạn không cần path-to-regexphoặc bất cứ điều gì nữa và bạn có thể sử dụng tham số tuyến trực tiếp trong đối số đầu tiên của usephương thức.
vdegenne

50

app.use là phương thức "cấp thấp hơn" từ Connect, khung phần mềm trung gian mà Express phụ thuộc vào.

Đây là hướng dẫn của tôi:

  • Sử dụng app.getnếu bạn muốn đưa ra một phương thức GET.
  • Sử dụng app.usenếu bạn muốn thêm một số phần mềm trung gian (trình xử lý cho yêu cầu HTTP trước khi đến các tuyến bạn đã thiết lập trong Express) hoặc nếu bạn muốn biến tuyến đường của mình thành mô-đun (ví dụ: hiển thị một bộ tuyến đường từ một mô-đun npm mà các ứng dụng web khác có thể sử dụng).

Nhưng nếu tôi không quan tâm đến phương pháp, tôi có thể sử dụng app.useđể xử lý một số tuyến đường không? Hoặc chúng ta không bao giờ nên sử dụng app.useđể định tuyến.
Elemento0

Bạn có thể sử dụng app.use để di chuyển các tuyến đường của mình để tách các tệp eq. users.js, tòa nhà.js
Rob Angelier

1
Mặc dù câu trả lời ở trên đã thu thập được nhiều UP / AGREE hơn, câu trả lời của bạn chuyển thứ tinh vi bao gồm Middleware thành một vài từ đơn giản, kudo.
Jeb50

50

Đơn giản là app.use có nghĩa là Chạy Run trên TẤT CẢ các yêu cầu.
Ứng dụng này có nghĩa là Chạy Run này trên một yêu cầu GET, đối với URL đã cho


Nó không đơn giản. Đọc câu trả lời khác.
David Lopez

28

app.getđược gọi khi phương thức HTTP được đặt thành GET, trong khi đó app.useđược gọi bất kể phương thức HTTP và do đó xác định một lớp nằm trên tất cả các loại RESTful khác mà các gói express cho phép bạn truy cập.


19

Sự khác biệt giữa app.use& app.get:

app.use → Nó thường được sử dụng để giới thiệu phần mềm trung gian trong ứng dụng của bạn và có thể xử lý tất cả các loại yêu cầu HTTP.

app.get → Nó chỉ để xử lý các yêu cầu GET HTTP.

Bây giờ, có một sự nhầm lẫn giữa app.use& app.all. Không còn nghi ngờ gì nữa, có một điều phổ biến ở họ, đó là cả hai đều có thể xử lý tất cả các loại yêu cầu HTTP. Nhưng có một số khác biệt khuyến nghị chúng tôi sử dụng app.use cho phần mềm trung gian và app.all để xử lý tuyến đường.

  1. app.use()→ Chỉ mất một cuộc gọi lại.
    app.all()→ Nó có thể mất nhiều cuộc gọi lại.

  2. app.use()sẽ chỉ xem liệu url bắt đầu với đường dẫn được chỉ định.
    Nhưng, app.all()sẽ phù hợp với con đường hoàn chỉnh.

Ví dụ,

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()cuộc gọi bên trong app.use()sẽ gọi hoặc là phần mềm trung gian tiếp theo hoặc bất kỳ trình xử lý tuyến đường nào, nhưng next()cuộc gọi bên trong app.all()sẽ chỉ gọi trình xử lý tuyến tiếp theo ( app.all(), app.get/post/put...v.v.). Nếu có bất kỳ phần mềm trung gian nào sau đó, nó sẽ bị bỏ qua. Vì vậy, nên đặt tất cả các phần mềm trung gian luôn ở trên trình xử lý tuyến.

1
Điểm 3 của bạn dường như không áp dụng trên Express 4.16. gọi next()bên trong app.all('/*', ...)ý chí trong thực tế sẽ thực hiện một app.use('/', ...)sau trong tập tin. Có lẽ tôi đã hiểu lầm bạn ở đó. Rất hữu ích giải thích khác.
BeetleJuice

Trong 4.17, tôi đã quan sát giống như @BeetleJuice
David Lopez

4

Ngoài những giải thích trên, những gì tôi trải nghiệm:

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

sẽ khớp với tất cả các yêu cầu bắt đầu bằng '/ book' dưới dạng URL. do đó, nó cũng khớp với '/ book / 1' hoặc '/ book / 2'

app.get('/book')  

chỉ khớp với yêu cầu NHẬN với kết hợp chính xác . Nó sẽ không xử lý các URL như '/ book / 1' hoặc '/ book / 2'

Vì vậy, nếu bạn muốn một trình xử lý toàn cầu xử lý tất cả các tuyến đường của bạn, thì đó app.use('/')là tùy chọn. app.get('/')sẽ chỉ xử lý URL gốc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.