ความแตกต่างระหว่าง app.all ('*') และ app.use ('/')


121

มีความแตกต่างที่เป็นประโยชน์ระหว่างapp.all('*', ... )และapp.use('/', ...)ใน Node.JS Express หรือไม่?

คำตอบ:


119

ในกรณีส่วนใหญ่พวกเขาจะทำงานได้เทียบเท่ากัน ความแตกต่างที่ใหญ่ที่สุดคือลำดับที่จะใช้มิดเดิลแวร์:

  • app.all() ยึดติดกับเราเตอร์ของแอปพลิเคชันดังนั้นจึงใช้เมื่อใดก็ตามที่ถึงมิดเดิลแวร์ของ app.router (ซึ่งจัดการเส้นทางเมธอดทั้งหมด ... GET, POST ฯลฯ )

ข้อสังเกต: app.router เลิกใช้งานแล้วใน Express 4.x

  • app.use()ยึดติดกับสแต็กมิดเดิลแวร์หลักของแอปพลิเคชันดังนั้นจึงใช้ตามลำดับที่มิดเดิลแวร์ระบุ เช่นถ้าคุณใส่มันก่อนมันจะเป็นสิ่งแรกที่จะเรียกใช้ หากคุณวางไว้ล่าสุด (หลังเราเตอร์) ก็มักจะไม่ทำงานเลย

โดยปกติแล้วหากคุณต้องการทำบางสิ่งทั่วโลกในทุกเส้นทาง app.use () เป็นตัวเลือกที่ดีกว่า นอกจากนี้ยังมีโอกาสน้อยที่จะเกิดข้อบกพร่องในอนาคตเนื่องจาก express 0.4 อาจจะทำให้เราเตอร์โดยปริยาย (หมายความว่าตำแหน่งของเราเตอร์ในมิดเดิลแวร์จะมีความสำคัญมากกว่าที่เป็นอยู่ในตอนนี้เนื่องจากในทางเทคนิคแล้วคุณไม่จำเป็นต้องใช้มันด้วยซ้ำ ตอนนี้)


15
สิ่งนี้ยังใช้ได้หลังจาก Express 4.x หรือไม่ app.router ถูกลบออก
ruffrey

1
คุณสามารถใช้next("route")กับapp.allแต่ใช้กับapp.use.
Jozef Mikušinec

@JozefMikusinec Documentation ดูเหมือนจะแนะนำเป็นอย่างอื่น ... expressjs.com/th/guide/writing-middleware.html
musicin3d

ลิงก์ของคุณไม่ได้กล่าวถึงถัดไป ('เส้นทาง') แต่ฉันดู API แล้วคุณพูดถูก
Jozef Mikušinec

2
@ musicin3d ฉันค้นคว้าเพิ่มเติมและพบปัญหา GitHub นี้ซึ่งยืนยันว่า "next () และ next ('route') ไม่มีความแตกต่างกับ app.use" (quote) พวกเขาควรเปลี่ยนเอกสาร
Jozef Mikušinec

87

app.useใช้ฟังก์ชันเรียกกลับเพียงฟังก์ชันเดียวและมีไว้สำหรับมิดเดิลแวร์ มิดเดิลแวร์มักจะไม่จัดการคำขอและการตอบกลับ (ในทางเทคนิคพวกเขาทำได้) เพียงแค่ประมวลผลข้อมูลอินพุตและส่งมอบให้กับตัวจัดการถัดไปในคิว

app.use([path], function)

app.allรับการโทรกลับหลายครั้งและมีไว้สำหรับการกำหนดเส้นทาง ด้วยการโทรกลับหลายครั้งคุณสามารถกรองคำขอและส่งการตอบกลับได้ อธิบายไว้ในFilters on express.js

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

app.useจะเห็นว่า url ขึ้นต้นด้วยเส้นทางที่ระบุเท่านั้นหรือไม่

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

app.allจะตรงกับเส้นทางที่สมบูรณ์

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

17
อย่างน้อยก็ในv4, app.useใช้เวลาหนึ่งหรือมากกว่ามิดเดิลแวร์ฟังก์ชั่นไม่ได้ "เพียงคนเดียว"
Jess Austin

2
app.use ดูว่า url ขึ้นต้นด้วยเส้นทางที่ระบุเท่านั้น app.all จะตรงกับเส้นทางที่สมบูรณ์ นี่คือความแตกต่างหลัก
meizilp

@frogcjn ไม่ควรเพราะมันเพิกเฉยต่อ * และ / ในคำถามของฉัน
ostergaard

15
  • app.use:

    1. ฉีดมิดเดิลแวร์ไปยังตัวควบคุมด้านหน้าของคุณที่กำหนดค่าเช่นส่วนหัวคุกกี้เซสชัน ฯลฯ
    2. ต้องเขียนก่อนแอป [http_method] มิฉะนั้นจะไม่ดำเนินการ
    3. การโทรหลายครั้งจะถูกประมวลผลตามลำดับการเขียน
  • app.all:

    1. (เช่นแอป [http_method]) ใช้สำหรับกำหนดค่าตัวควบคุมเส้นทาง
    2. "all" หมายความว่าใช้กับวิธี http ทั้งหมด
    3. การโทรหลายครั้งจะถูกประมวลผลตามลำดับการเขียน

ดูตัวอย่างโค้ด 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);

นี่คือบันทึกเมื่อเข้าถึงเส้นทาง '/ สวัสดี':

(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

6
หลังจากรันตัวอย่างคำต่อคำบน express 4.x แล้วมันจะทำงานทั้ง 5 ตามลำดับ น่าจะเกิดจากการเปลี่ยนแปลงใน Express ในช่วงเกือบ 3 ปีนับตั้งแต่มีการเขียนขึ้น แต่ฉันคิดว่าจะเพิ่มสิ่งนี้เพื่อความชัดเจน
Nathan Wiebe

11

ด้วยapp.use()พา ธ "mount" ถูกถอดออกและมองไม่เห็นฟังก์ชันมิดเดิลแวร์:

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

ฟังก์ชันมิดเดิลแวร์ที่ต่อเชื่อม ( express.static) จะไม่ถูกเรียกใช้เว้นแต่จะreq.urlมีคำนำหน้านี้ ( /static) ซึ่งจะถูกขีดฆ่าเมื่อเรียกใช้ฟังก์ชัน

ด้วยapp.all()ไม่มีพฤติกรรมนั้น


คำถามนี้ถามอย่างชัดเจนเกี่ยวกับ app.use ('/', ... ) เท่านั้น
ostergaard

นี่คือคำตอบที่ถูกต้องสำหรับคำถามซึ่งยังคงเป็นจริงในปี 2018! มิดเดิลแวร์สามารถติดตั้งกับ all () ได้เช่นกัน ... ข้อแตกต่างเพียงอย่างเดียวคือเส้นทางการเชื่อมต่อถูกถอดออกเมื่อเรียกใช้มิดเดิลแวร์
Xatian

4

ใช่app.all()ถูกเรียกเมื่อมีการร้องขอ URI โดยเฉพาะด้วยวิธีการร้องขอประเภทใดก็ได้ (POST, GET, PUT หรือ DELETE)

ในทางกลับกันapp.use()ใช้สำหรับมิดเดิลแวร์ใด ๆ ที่คุณอาจมีและจะเชื่อมต่อกับคำนำหน้าพา ธ และจะถูกเรียกเมื่อใดก็ตามที่มีการร้องขอ URI ภายใต้เส้นทางนั้น

นี่เป็นวิธีการใช้app.all & app.use


ขอบคุณ แต่ฉันคิดว่าคุณพลาดแอพตัวแทนและแอพทั้งหมดใช้เส้นทางรูทซึ่งทำให้พวกเขาค่อนข้างเหมือนกันทุกประการใช่ไหม ยกเว้นว่า app.all สามารถรับอาร์เรย์ของการโทรกลับและ app.use สามารถรับได้เพียงครั้งเดียวใช่ไหม
ostergaard

1

ความแตกต่างสองคำตอบทั้งหมดข้างต้นไม่ได้เป็นคำตอบ

fisrt one: app.allยอมรับ regex เป็นพารามิเตอร์ path app.useไม่ยอมรับนิพจน์ทั่วไป

คนที่สอง: app.all(path,handler)หรือapp[method](path,handler)ของการจัดการpathจะต้องเหมือนกันไปทั้งหมด pathนี่คือเส้นทางของแอป [วิธีการ] เสร็จสมบูรณ์

app.use(path,hanlder)หากเส้นทางของการใช้งานเสร็จสมบูรณ์เส้นทางของแฮนเดอร์จะต้องเป็น '/' หากเส้นทางของการใช้เป็นจุดเริ่มต้นของเส้นทางที่สมบูรณ์เส้นทางตัวจัดการจะต้องเป็นส่วนที่เหลือของเส้นทางที่สมบูรณ์

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

0

มีสองความแตกต่างหลักคือ

1. รูปแบบการจับคู่ (คำตอบที่ได้รับจากพาลานี)
2. จะไม่ทำงานภายในร่างกายทำงานของมิดเดิ้ลถูกเรียกใช้งานnext(route) app.useสิ่งนี้ระบุไว้ในลิงค์จากเอกสาร:

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

ลิงก์: http://expressjs.com/en/guide/using-middleware.html

ผลการทำงานnext('route')สามารถเห็นได้จากตัวอย่างต่อไปนี้:

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();});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.