ความแตกต่างระหว่าง app.use และ app.get in 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/...
เบนจามิน Gruenbaum

ใช่คำตอบที่ดีทั้งหมด ขอบคุณฉันจะดูที่
Andre Vorobyov

คำตอบ:


219

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

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

    เมื่อเทียบกับ

    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      // ...
    });
  • ด้วยตัวจัดการหลายตัวสำหรับเส้นทางเดียวกัน:

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

    เมื่อเทียบกับ

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

    เมื่อเทียบกับ

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

หมายเหตุ: การดำเนินการด่วนของคุณสมบัติเหล่านี้มีอยู่ในตนRouter,LayerRouteและ


3
รุ่งโรจน์สำหรับการกล่าวถึงแอพที่ฝังตัว มันเป็นวิธีที่สะดวกมากในการจัดระเบียบมิดเดิลแวร์แบบด่วน
wprl

4
มันยุติธรรมหรือไม่ที่จะบอกว่า app.use สามารถทำทุกอย่างของ app.get, app.post, app.put ได้ แต่ไม่ใช่ในทางกลับกัน?
ngungo

6
ยังยากที่จะเข้าใจ
Jeb50

1
มันเป็นเรื่องดีที่จะรู้ว่าสิ่งที่ใช้และได้รับมีสำหรับแต่ไม่มีใครได้งานที่ดีของการอธิบายวิธีการทำงานที่แตกต่างกัน จากสิ่งที่ฉันสามารถรวบรวมได้ตัวจัดการ. use ทั้งหมดจะทำงานก่อนและ .use ตรงกับเส้นทางใด ๆ ที่ขึ้นต้นด้วยเส้นทางที่ระบุ (เช่น. use ('/', ... ) และ. get ('/ *', ... ) จะตรงกับเส้นทางเดียวกัน) สำหรับฉันมันง่ายกว่าที่จะเข้าใจแนวคิดโดยรวมเมื่อฉันเห็นชิ้นส่วนที่เคลื่อนไหว
snarf

2
ฉันคิดว่ามันไม่คุ้มค่าที่คำตอบนี้เก่าและล้าสมัย ณ วันที่ความคิดเห็นของฉันที่คุณไม่ต้องการpath-to-regexpหรืออะไรอีกต่อไปและคุณสามารถใช้พารามิเตอร์เส้นทางในอาร์กิวเมนต์แรกของuseวิธีการได้โดยตรง
vdegenne

50

app.use เป็นวิธี "ระดับที่ต่ำกว่า" จากการเชื่อมต่อกรอบมิดเดิลแวร์ที่ Express ขึ้นอยู่กับ

นี่คือแนวทางของฉัน:

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

แต่ถ้าฉันไม่สนใจวิธีนี้ฉันสามารถใช้app.useเพื่อจัดการเส้นทางบางเส้นทางได้หรือไม่ หรือเราไม่ควรใช้app.useสำหรับการกำหนดเส้นทาง
Elemento0

คุณสามารถใช้ app.use เพื่อย้ายเส้นทางของคุณเพื่อแยกไฟล์ eq users.js, buildings.js
Rob Angelier

1
แม้ว่าคำตอบเดียวข้างต้นนี้ได้รวบรวม UP / AGREE มากขึ้นคำตอบของคุณแปลสิ่งที่ซับซ้อนรวมถึง Middleware ให้เป็นคำง่ายๆสองสามคำ kudo
Jeb50

50

เพียงแค่ app.use หมายถึง“ เรียกใช้สิ่งนี้กับคำขอทั้งหมด”
app.get หมายถึง“ เรียกใช้สิ่งนี้ตามคำขอ GET สำหรับ URL ที่ระบุ”


มันไม่ง่ายอย่างนั้น อ่านคำตอบอื่น ๆ
David Lopez

28

app.getถูกเรียกเมื่อตั้งค่าวิธี HTTPGETในขณะที่app.useเรียกว่าโดยไม่คำนึงถึงวิธี HTTP และดังนั้นจึงกำหนดชั้นที่อยู่ด้านบนของประเภท RESTful อื่น ๆ ทั้งหมดที่แพคเกจด่วนให้คุณเข้าถึง


19

ความแตกต่างระหว่างapp.use& app.get:

app.use →โดยทั่วไปจะใช้สำหรับการแนะนำมิดเดิลแวร์ในแอปพลิเคชันของคุณและสามารถรองรับการร้องขอ HTTP ทุกประเภท

app.get →เป็นเพียงการจัดการคำขอ GET HTTP เท่านั้น

ขณะนี้มีความสับสนระหว่าง&app.use app.allไม่ต้องสงสัยเลยว่ามีสิ่งหนึ่งที่พบได้ทั่วไปคือทั้งคู่สามารถจัดการคำขอ HTTP ทุกประเภทได้ แต่มีข้อแตกต่างบางประการที่แนะนำให้เราใช้ app.use สำหรับ middlewares และ 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
David Lopez

4

นอกจากคำอธิบายข้างต้นสิ่งที่ฉันได้รับ:

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

จะจับคู่คำขอทั้งหมดที่ขึ้นต้นด้วย '/ book' เป็น URL ดังนั้นจึงตรงกับ '/ หนังสือ / 1' หรือ '/ หนังสือ / 2'

app.get('/book')  

การแข่งขันจะได้รับการร้องขอกับการแข่งขันที่แน่นอน จะไม่จัดการ URL เช่น '/ book / 1' หรือ '/ book / 2'

ดังนั้นหากคุณต้องการตัวจัดการทั่วโลกที่จัดการเส้นทางทั้งหมดของคุณนั้นapp.use('/')เป็นตัวเลือก app.get('/')จะจัดการ URL หลักเท่านั้น

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