การส่งตัวแปรไปยังมิดเดิลแวร์ถัดไปโดยใช้ next () ใน Express.js


200

คำถามของฉันคือฉันต้องการส่งตัวแปรบางตัวจากมิดเดิลแวร์แรกไปยังมิดเดิลแวร์อื่นและฉันลองทำสิ่งนี้ แต่มี " req.somevariableถูกกำหนดเป็น 'ไม่ได้กำหนด'"


//app.js
..
app.get('/someurl/', middleware1, middleware2)
...

////middleware1
...
some conditions
...
res.somevariable = variable1;
next();
...

////middleware2
...
some conditions
...
variable = req.somevariable;
...

ควรทำงาน. นอกจากว่ามันเป็นตัวพิมพ์ผิดในคำถามที่คุณอาจล้มเหลวเพราะคุณกำหนดค่าให้กับresในมิดเดิลแวร์ 1 และพยายามที่จะรับมันจากreqในมิดเดิลแวร์ 2
Andreas Hultgren

Thankz @AndreasHultgren
2791897

Local variables are available in middleware via req.app.locals expressjs.com/pt-br/api.html#app.locals
Ronnie Royston

คำตอบ:


202

แนบตัวแปรของคุณไปยังวัตถุไม่ได้reqres

แทน

res.somevariable = variable1;

มี:

req.somevariable = variable1;

ดังที่คนอื่น ๆ ชี้ให้เห็นres.localsเป็นวิธีที่แนะนำในการส่งผ่านข้อมูลผ่านมิดเดิลแวร์


13
ใช้ res.locals.variable = var; ดูคำตอบอื่น ๆ
godzsa

1
เพื่อดึงตัวแปรใช้ req.res.locals.variable ในฟังก์ชั่นมิดเดิลแวร์ถัดไป
William Wu

3
@WilliamWu ของมันไม่ได้res.locals req.res.locals
cchamberlain

2
res.locals.myVarเป็นวิธีที่จะไป
jasonseminara

447

นี่คือสิ่งที่วัตถุres.localsสำหรับ การตั้งค่าตัวแปรโดยตรงบนวัตถุที่ร้องขอไม่ได้รับการสนับสนุนหรือบันทึกไว้ res.localsรับประกันว่าจะเก็บสถานะตลอดชีวิตของการร้องขอ

res.locals

วัตถุที่มีตัวแปรโลคัลการตอบสนองที่กำหนดขอบเขตไว้ที่การร้องขอดังนั้นจึงมีให้เฉพาะกับมุมมองที่แสดงผลระหว่างการร้องขอ / การตอบสนองรอบนั้น (ถ้ามี) มิฉะนั้นคุณสมบัตินี้จะเหมือนกับ app.locals

คุณสมบัตินี้มีประโยชน์สำหรับการเปิดเผยข้อมูลระดับคำขอเช่นชื่อพา ธ คำขอผู้ใช้ที่ผ่านการตรวจสอบความถูกต้องการตั้งค่าผู้ใช้และอื่น ๆ

app.use(function(req, res, next) {
    res.locals.user = req.user;  
    res.locals.authenticated = !req.user.anonymous;
    next();
});

ในการดึงตัวแปรในมิดเดิลแวร์ถัดไป:

app.use(function(req, res, next) {
    if (res.locals.authenticated) {
        console.log(res.locals.user.id);
    }
    next();
});

66
ไม่ทราบว่าทำไมนี้ไม่ได้เป็นคำตอบที่ได้รับการยอมรับนี้เป็นเอกสารวิธีการตั้งค่าตัวแปรจากมิดเดิ้ลตลอดการร้องขอ
Sam Holmes

11
res.locals มีวัตถุประสงค์ที่จะใช้โดยมุมมองที่จะแสดงผลในที่สุดในช่วงวงจรชีวิตของการร้องขอนี้เป็นสิ่งที่เอกสารพูด หากคุณไม่ได้ใช้มุมมองมันเกินความจริงที่จะวางสิ่งต่าง ๆ บนวัตถุในท้องถิ่นและไม่ใช่แบบแผน ในกรณีเหล่านี้ฉันมักจะสนับสนุนให้ผู้คนยึดติดกับการประชุมเพื่อให้เราสามารถลดภาระการรับรู้ในขณะที่เรียนรู้แนวคิดเช่น Express หรือขอวงจรชีวิต
real_ate

2
@real_ate ที่เป็นการใช้งานหลักของ res.locals แต่ไม่ได้ตอบคำถาม OPs การส่งคำร้องขอตัวแปรที่กำหนดขอบเขตไปยังมิดเดิลแวร์ในอนาคตบางครั้งมีความจำเป็นเวลาที่ฉันได้รับมันมักจะเกี่ยวกับการรับรองความถูกต้องของผู้ใช้ในมิดเดิลแวร์ต้นซึ่งตั้งค่าการอ้างสิทธิ์ที่ได้รับการกำหนดเส้นทาง
cchamberlain

14
เอกสารด่วนสำหรับการเขียนตัวแปรชุดตัวกลางในreqวัตถุexpressjs.com/en/guide/writing-middleware.html ดูที่ส่วนMiddleware function requestTime
ปลาดุก

2
@ คนแปลยืนยันว่าโชคดีที่ไม่ใช่วิธีการตอบสนอง การตอบสนองจะถูกส่งโดยการเรียกคุณสมบัติการทำงานของวัตถุการตอบสนองเช่นres.json({})ฯลฯres.localsจะใช้ได้เฉพาะในส่วนแบ็คเอนด์ตลอดอายุของการร้องขอ expressjs.com/en/5x/api.html
cchamberlain

22

req.YOUR_VARผมไม่คิดว่าการปฏิบัติที่ดีที่สุดจะได้รับการส่งผ่านตัวแปรเช่น คุณอาจต้องการที่จะต้องพิจารณาหรือreq.YOUR_APP_NAME.YOUR_VARreq.mw_params.YOUR_VAR

มันจะช่วยให้คุณหลีกเลี่ยงการเขียนทับคุณสมบัติอื่น ๆ

อัปเดต 31 พฤษภาคม 2020

res.localsคือสิ่งที่คุณกำลังค้นหาวัตถุถูกกำหนดขอบเขตให้กับคำขอ

วัตถุที่มีตัวแปรโลคัลการตอบสนองที่กำหนดขอบเขตไว้ที่การร้องขอดังนั้นจึงมีให้เฉพาะกับมุมมองที่แสดงผลระหว่างการร้องขอ / การตอบสนองรอบนั้น (ถ้ามี) มิฉะนั้นคุณสมบัตินี้จะเหมือนกับ app.locals

คุณสมบัตินี้มีประโยชน์สำหรับการเปิดเผยข้อมูลระดับคำขอเช่นชื่อพา ธ คำขอผู้ใช้ที่ผ่านการตรวจสอบความถูกต้องการตั้งค่าผู้ใช้และอื่น ๆ


2
คุณจะแนะนำให้ตั้งค่าreq.YOUR_APP_NAME = {}เริ่มต้นอย่างไร คุณเพียงแค่พยายามเขียนถึงreq.YOUR_APP_NAME.someVarคุณจะได้รับข้อผิดพลาดตามที่req.YOUR_APP_NAMEยังไม่ได้กำหนด
Kousha

2
@Kousha คุณสามารถเขียนเราเตอร์มิดเดิลแวร์ที่ด้านบนสุดของสคริปต์การกำหนดเส้นทางของคุณ:router.use(function(req,res,next){req.YOUR_APP_NAME = {};next()})
โทมัส

มีวิธีผ่านเป็น param ด้วยฟังก์ชัน () ถัดไปหรือไม่ ชอบต่อไป (myObj)
philx_x

1
@Kousha - ข้อผิดพลาดที่ไม่ได้กำหนดไม่มีอะไรเกี่ยวข้องกับ express คุณกำลังพยายามกำหนดคุณสมบัติให้กับวัตถุที่ไม่มีอยู่จริง req.APP_NS = req.APP_NS || {}; req.APP_NS.somevar = 'value'โดยปกติการทำเช่นนี้คุณจะใช้
cchamberlain

1
@philx_x หากคุณส่งพารามิเตอร์ใด ๆ ไปยังnextฟังก์ชั่นมันจะทำให้เกิดข้อผิดพลาด 'ด่วนจัดการและเลื่อนออก ตรวจสอบเอกสาร
Merl

7

นั่นเป็นเพราะreqและresเป็นวัตถุสองอย่างที่แตกต่างกัน

คุณต้องค้นหาคุณสมบัติบนวัตถุเดียวกันกับที่คุณเพิ่มเข้าไป


3

เคล็ดลับง่าย ๆ ... รอบคำขอยังมีชีวิตอยู่ค่อนข้างมาก คุณสามารถเพิ่มตัวแปรใหม่ที่จะสร้างการโทรชั่วคราว

app.get('some/url/endpoint', middleware1, middleware2);

เนื่องจากคุณสามารถจัดการคำขอของคุณในมิดเดิลแวร์แรก

(req, res, next) => {
    var yourvalue = anyvalue
}

ในมิดเดิลแวร์ 1 คุณจัดการตรรกะของคุณและเก็บค่าของคุณเช่นด้านล่าง:

req.anyvariable = yourvalue

ในมิดเดิลแวร์ 2 คุณสามารถรับค่านี้จากมิดเดิลแวร์ 1 ทำสิ่งต่อไปนี้:

(req, res, next) => {
    var storedvalue = req.yourvalue
}

1

ดังที่กล่าวข้างต้น res.locals เป็นวิธีที่ดี (แนะนำ) ในการทำเช่นนี้ ดูที่นี่สำหรับบทช่วยสอนด่วนเกี่ยวกับวิธีการทำสิ่งนี้ใน Express

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