एक्सप्रेस में "अगला" किस पैरामीटर के लिए उपयोग किया जाता है?


295

मान लीजिए कि आपके पास इस तरह का एक सरल ब्लॉक है:

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

इस फ़ंक्शन के दो पैरामीटर हैं, reqऔर res, जो क्रमशः अनुरोध और प्रतिक्रिया वस्तुओं का प्रतिनिधित्व करते हैं।

दूसरी ओर, तीसरे पैरामीटर के साथ अन्य फ़ंक्शन हैं जिन्हें कहा जाता है next। उदाहरण के लिए, निम्नलिखित कोड पर एक नजर डालते हैं:

app.get('/users/:id?', function(req, res, next){ // Why do we need next?
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next(); // What is this doing?
    }
});

मैं समझ नहीं पा रहा हूं next()कि इसका क्या मतलब है या इसका इस्तेमाल क्यों किया जा रहा है। उस उदाहरण में, यदि आईडी मौजूद नहीं है, तो nextवास्तव में क्या हो रहा है?


13
अगला बस अनुरोध को संभालने के लिए लाइन में अगले मार्ग हैंडलर की अनुमति देता है। इस स्थिति में, यदि उपयोगकर्ता आईडी मौजूद है, तो यह res.sendअनुरोध को पूरा करने के लिए उपयोग करेगा । यदि यह मौजूद नहीं है, तो एक और हैंडलर होने की संभावना है जो एक त्रुटि जारी करेगा और फिर अनुरोध पूरा करेगा।
डोमिनिक बार्न्स

1
तो आप कह रहे हैं कि मेरे पास एक के app.post('/login',function(req,res))बाद एक app.get('/users',function(req,res)) लॉगिन होगा जो ऐप में अगला मार्ग है। जेएस फ़ाइल को अगला () कॉल करके?
मेन्स्ट्रूचुअल

2
नहीं, आपको Express.js प्रलेखन के इस भाग को संदर्भित करना चाहिए: expressjs.com/guide.html#passing-route नियंत्रण
डोमिनिक बार्न्स

3
मूल रूप से, चलाया जाने वाला अगला मार्ग एक और होगा जो अनुरोध के लिए URL से मेल खाता है। इस मामले में, यदि किसी अन्य मार्ग के माध्यम से पंजीकृत किया गया था app.get("/users"), तो इसे चलाया जाएगा यदि हैंडलर ऊपर कॉल के बाद।
डोमिनिक बार्न्स

3
अगला मूल रूप से सिर्फ एक कॉलबैक है।
जोनाथन ओंग

जवाबों:


266

यह अगले मिलान मार्ग पर नियंत्रण से गुजरता है । उदाहरण के लिए, उदाहरण के लिए, आप डेटाबेस में उपयोगकर्ता को देख सकते हैं यदि कोई idदिया गया था, और उसे असाइन करें req.user

नीचे, आपके पास एक मार्ग हो सकता है जैसे:

app.get('/users', function(req, res) {
  // check for and maybe do something with req.user
});

चूंकि / उपयोगकर्ता / 123 पहले आपके उदाहरण में मार्ग से मेल खाएगा, जो पहले उपयोगकर्ता की जांच करेगा और ढूंढेगा 123; तो /usersउस के परिणाम के साथ कुछ कर सकते हैं।

रूट मिडलवेयर एक अधिक लचीला और शक्तिशाली उपकरण है, हालांकि, मेरी राय में, चूंकि यह एक विशेष यूआरआई योजना या मार्ग आदेश पर भरोसा नहीं करता है। मैं इस तरह से दिखाए गए उदाहरण को मॉडल करने के लिए इच्छुक हूं, एक Usersमॉडल को एक async के साथ मानते हुए findOne():

function loadUser(req, res, next) {
  if (req.params.userId) {
    Users.findOne({ id: req.params.userId }, function(err, user) {
      if (err) {
        next(new Error("Couldn't find user: " + err));
        return;
      }

      req.user = user;
      next();
    });
  } else {
    next();
  }
}

// ...

app.get('/user/:userId', loadUser, function(req, res) {
  // do something with req.user
});

app.get('/users/:userId?', loadUser, function(req, res) {
  // if req.user was set, it's because userId was specified (and we found the user).
});

// Pretend there's a "loadItem()" which operates similarly, but with itemId.
app.get('/item/:itemId/addTo/:userId', loadItem, loadUser, function(req, res) {
  req.user.items.append(req.item.name);
});

इस तरह प्रवाह को नियंत्रित करने में सक्षम होना बहुत आसान है। आप चाहते हैं कि कुछ पृष्ठ केवल उन उपयोगकर्ताओं के लिए उपलब्ध हों जो किसी व्यवस्थापक ध्वज के साथ उपलब्ध हों:

/**
 * Only allows the page to be accessed if the user is an admin.
 * Requires use of `loadUser` middleware.
 */
function requireAdmin(req, res, next) {
  if (!req.user || !req.user.admin) {
    next(new Error("Permission denied."));
    return;
  }

  next();
}

app.get('/top/secret', loadUser, requireAdmin, function(req, res) {
  res.send('blahblahblah');
});

आशा है कि इससे आपको कुछ प्रेरणा मिली होगी!


तुम ये कह सकते हो! मैं रूट मिडलवेयर के साथ इस तरह का काम करने के लिए अधिक इच्छुक हूं , हालांकि, यह मार्गों के एक विशेष क्रम, या विशेष रूप से URI संरचनाओं को तर्क नहीं देता है।
अशेरह

5
कभी-कभी आप आगे क्यों लौटते हैं () लेकिन कभी-कभी नहीं
जॉन

6
@ जॉन: रिटर्न वैल्यू को वास्तव में अनदेखा किया जाता है; मैं केवल यह सुनिश्चित करने के लिए वहां लौटना चाहता हूं कि मैं next()फिर से फोन न करूं । यह वैसा ही होगा यदि मैं अभी उपयोग करता हूं next(new Error(…)); return;
अशरह

1
@ स्तर 0: रिटर्न मान को अनदेखा किया जाता है; आप इसके लिए आशुलिपि पर विचार कर सकते हैं next(new Error(…)); return;। यदि हम एक मान पास करते हैं next, तो यह एकतरफा त्रुटि माना जाता है । मैंने एक्सप्रेस कोड में बहुत अधिक नहीं देखा है, लेकिन चारों ओर खुदाई करें और आप पाएंगे कि आपको क्या चाहिए :)
अशेराह

1
@ स्तर 0: (मैं बदल गया return next(…);है next(…); return;इसलिए यह कम भ्रमित करने वाला है।)
आशेराह

87

मुझे अगली समझने में भी समस्या थी (), लेकिन इससे मदद मिली

var app = require("express")();

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write("Hello");
    next(); //remove this and see what happens 
});

app.get("/", function(httpRequest, httpResponse, next){
    httpResponse.write(" World !!!");
    httpResponse.end();
});

app.listen(8080);

3
बहुत रसीली! धन्यवाद! लेकिन आप यह कैसे सुनिश्चित करेंगे कि पहले .getको बुलाया जाए और दूसरे को नहीं?
जॉनीक्यू

18
@ जॉनीक्यू यह शीर्ष से नीचे तक निष्पादन होगा
तपश

59

समझने से पहले next, आपको नोड में रिक्वेस्ट-रिस्पॉन्स चक्र का थोड़ा विचार करना होगा, हालांकि विस्तार में ज्यादा नहीं। यह आपके लिए एक विशेष संसाधन के लिए HTTP अनुरोध करने के साथ शुरू होता है और यह तब समाप्त होता है जब आप उपयोगकर्ता को एक प्रतिक्रिया भेजते हैं अर्थात जब आप res.send ('हैलो वर्ल्ड') जैसी किसी चीज़ का सामना करते हैं;

आइए एक बहुत ही सरल उदाहरण देखें।

app.get('/hello', function (req, res, next) {
  res.send('USER')
})

यहां हमें अगले () की आवश्यकता नहीं है, क्योंकि resp.send चक्र को समाप्त करेगा और नियंत्रण को वापस मार्ग के मध्य में सौंप देगा।

अब एक और उदाहरण लेते हैं।

app.get('/hello', function (req, res, next) {
  res.send("Hello World !!!!");
});

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

यहां हमारे पास एक ही पथ के लिए 2 मिडलवेयर फ़ंक्शन हैं। लेकिन आप हमेशा पहले वाले से प्रतिक्रिया प्राप्त करने वाले हैं। क्योंकि यह मिडिलवेयर स्टैक में सबसे पहले लगाया जाता है और रिससेंड चक्र को समाप्त कर देगा।

लेकिन क्या होगा अगर हम हमेशा "हैलो वर्ल्ड !!!!" नहीं चाहते हैं प्रतिक्रिया वापस। कुछ स्थितियों के लिए हम "हेलो प्लेनेट !!!!" चाहते हैं। प्रतिक्रिया। आइए उपरोक्त कोड को संशोधित करें और देखें कि क्या होता है।

app.get('/hello', function (req, res, next) {
  if(some condition){
    next();
    return;
  }
  res.send("Hello World !!!!");  
});

app.get('/hello', function (req, res, next) {
  res.send("Hello Planet !!!!");
});

यहाँ क्या nextकर रहा है? और हाँ आप gusses हो सकता है। यदि स्थिति सही है तो यह पहले मिडलवेयर फ़ंक्शन को स्किप करने वाला है और अगले मिडलवेयर फ़ंक्शन को इनवॉइस करें और आपके पास "Hello Planet !!!!"प्रतिक्रिया होगी ।

तो, अगले मिडलवेयर स्टैक में अगले फ़ंक्शन पर नियंत्रण पास करें।

क्या होगा अगर पहला मिडलवेयर फ़ंक्शन किसी भी प्रतिक्रिया को वापस नहीं भेजता है, लेकिन तर्क के एक टुकड़े को निष्पादित करता है और फिर आपको दूसरे सॉफ़्टवेयर फ़ंक्शन से प्रतिक्रिया वापस मिलती है।

कुछ इस प्रकार है: -

app.get('/hello', function (req, res, next) {
  // Your piece of logic
  next();
});

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

इस मामले में आपको आमंत्रित करने के लिए दोनों मिडलवेयर फ़ंक्शंस की आवश्यकता है। तो, दूसरे मिडलवेयर फ़ंक्शन तक पहुंचने का एकमात्र तरीका अगले कॉल करके है ();

क्या होगा अगर आप अगले को कॉल नहीं करते हैं। दूसरे मिडलवेयर फ़ंक्शन को स्वचालित रूप से प्राप्त करने की अपेक्षा न करें। पहले फ़ंक्शन को लागू करने के बाद आपका अनुरोध लटका रह जाएगा। दूसरा फ़ंक्शन कभी भी लागू नहीं होगा और आपको प्रतिक्रिया वापस नहीं मिलेगी।


तो एक हार्ड-वायर्ड लेबल के साथ next()प्रदर्शन करता है goto? यानी आपके तीसरे स्निपेट में, एक बार कॉल करने के बाद next(), res.send("Hello World !!!!"); कभी भी निष्पादित नहीं किया जाएगा? मैंने देखा कि @Ashe के पास हमेशा एक कॉल के return;बाद एक nextही निष्पादन ट्री में कोड था ... लगता है कि मैं हमेशा एक्सप्रेस में जांच सकता हूं, हुह? / उसके पाठ संपादक के लिए खत्म हो चलाता है;)
Ruffin

@ruffin हाँ, आप एक गोटो के आगे के बारे में सोच सकते हैं। लेकिन अगला जानता है कि गोटो के विपरीत कहाँ जाना है जिसके लिए एक लेबल की आवश्यकता होती है। अगला नियंत्रण अगले मिडलवेयर फ़ंक्शन को पास करेगा। इसके अलावा, आप अपनी पसंद के अनुसार 'अगला' नाम रख सकते हैं। यह यहां सिर्फ एक लेबल है। लेकिन सबसे अच्छा अभ्यास 'अगला' नाम का उपयोग करना है
मावे

3
ठीक है, लगता है कि यह सही नहीं है। मैंने कोड ( pastebin यहाँ ) की कोशिश की , और next()कॉल के बाद कोड कहा जाता है । इस मामले में, past the next() callकंसोल को लिखा जाता है, और फिर मुझे एक Error: Can't set headers after they are sent.त्रुटि मिलती है , जैसा कि दूसरा res.sendकहा जाता है, हालांकि असफल रूप से। कोड प्रवाह कॉल के बाद वापसnext() आता है, जो @ एशेज returns(या अन्य तर्क प्रबंधन) को महत्वपूर्ण बनाता है ।
रफिन

4
@ruffin, हाँ, आप सही हैं। हमें next()शेष बयानों के निष्पादन को छोड़ देने के बाद रिटर्न स्टेटमेंट की आवश्यकता है । यह इंगित करने के लिए धन्यवाद।
माव 55

1
वास्तव में यह समझाने के लिए धन्यवाद कि "मिडलवेयर" क्या है / w / स्पष्ट उदाहरण हैं और न कि केवल दस्तावेज को तोता। यह एकमात्र उत्तर था जो वास्तव में कुछ भी स्पष्ट कहता है कि क्या होता है, क्यों और कैसे होता है।
mc01

11

अगला का उपयोग अगले मिडलवेयर फ़ंक्शन पर नियंत्रण पास करने के लिए किया जाता है। नहीं तो अनुरोध लटका या खुला छोड़ दिया जाएगा।


6
मुझे यकीन नहीं है कि यह उत्तर लगभग सात वर्षीय प्रश्न में क्या जोड़ता है ...
मैहरजिग

हालांकि संक्षिप्त, यह टिप्पणी मुझे इस तक ले जाती है: expressjs.com/en/guide/writing-middleware.html
hmak

@mherzig, यह एक लाइनर है और सब कुछ कवर करता है
एम। गोपाल

5

इस फ़ंक्शन को कॉल करना ऐप में अगले मिडलवेयर फ़ंक्शन को आमंत्रित करता है। अगला () फ़ंक्शन Node.js या Express API का हिस्सा नहीं है, लेकिन तीसरा तर्क है जो मिडलवेयर फ़ंक्शन को दिया जाता है। अगले () फ़ंक्शन को कुछ भी नाम दिया जा सकता है, लेकिन सम्मेलन द्वारा इसे हमेशा "अगला" नाम दिया जाता है।


2

nextफ़ंक्शन को निष्पादित करना उस सर्वर को सूचित करता है जिसे आप इस मिडलवेयर चरण के साथ करते हैं और यह श्रृंखला में अगले चरण को निष्पादित कर सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.