अगले का उपयोग कब करें () और अगले पर वापस जाएँ () Node.js में


136

परिदृश्य : निम्न पर विचार करें नोड वेब ऐप से कोड का हिस्सा है।

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next(); //or return next();
    }
});

मुद्दा : मैं जो एक बस के साथ जाने के जाँच कर रहा हूँ next()या return next()। ऊपर का नमूना कोड दोनों के लिए समान रूप से काम करता है और निष्पादन में कोई अंतर नहीं दिखा।

प्रश्न : क्या कोई इस पर प्रकाश डाल सकता है, कब उपयोग करना है next()और कब उपयोग करना है return next()और कुछ महत्वपूर्ण अंतर है?

जवाबों:


141

कुछ लोग हमेशा लिखते हैं return next()कि कॉलबैक को ट्रिगर करने के बाद निष्पादन बंद हो जाता है।

यदि आप ऐसा नहीं करते हैं, तो आप दूसरी बार कॉलबैक को ट्रिगर करने का जोखिम उठाते हैं, जिसमें आमतौर पर विनाशकारी परिणाम होते हैं। आपका कोड ठीक है जैसा कि यह है, लेकिन मैं इसे फिर से लिखूंगा:

app.get('/users/:id?', function(req, res, next){
    var id = req.params.id;

    if(!id)
        return next();

    // do something
});

यह मुझे एक इंडेंटेशन स्तर बचाता है, और जब मैं बाद में कोड फिर से पढ़ता हूं, तो मुझे यकीन है कि कोई रास्ता नहीं nextहै दो बार कहा जाता है।


2
क्या इस प्रकार की स्थिति में res.redirect('/')बनाम की बात सच होगी return res.redirect('/')? हो सकता है कि भेजे जाने के बाद हेडर सेट करने की त्रुटियों से बचने के लिए रिज़ॉर्ट स्टेटमेंट के सामने हमेशा रिटर्न लिखना बेहतर हो?
एडम डी।

185

@ लॉरेंट पेरिन के उत्तर के रूप में:

यदि आप ऐसा नहीं करते हैं, तो आप दूसरी बार कॉलबैक को ट्रिगर करने का जोखिम उठाते हैं, जिसमें आमतौर पर विनाशकारी परिणाम होते हैं

यदि आप इस तरह से मिडलवेयर लिखते हैं तो मैं यहां एक उदाहरण देता हूं:

app.use((req, res, next) => {
  console.log('This is a middleware')
  next()
  console.log('This is first-half middleware')
})

app.use((req, res, next) => {
  console.log('This is second middleware')
  next()
})

app.use((req, res, next) => {
  console.log('This is third middleware')
  next()
})

आपको पता चलेगा कि कंसोल में आउटपुट है:

This is a middleware
This is second middleware
This is third middleware
This is first-half middleware

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

हालाँकि, यदि आप उपयोग करते हैं return next(), तो यह तुरंत return next()कॉलबैक को छोड़ देगा और कॉलबैक में नीचे का कोड अनुपलब्ध होगा।


29
expressइस उत्तर के लिए एक शुरुआत के रूप में अन्य उत्तरों की तुलना में मेरे लिए चीजें स्पष्ट हो गईं। थम्स अप!
मंडारिन

1
क्या इस प्रकार की स्थिति में res.redirect('/')बनाम की बात सच होगी return res.redirect('/')? हो सकता है कि भेजने के बाद हेडर सेट करने की त्रुटियों से बचने के लिए हमेशा बयानों के returnसामने लिखना बेहतर हो res?
एडम डी।

1
मुझे अगले () के बाद कोड क्यों लिखना चाहिए? क्या यह स्पष्ट नहीं है कि एक मिडलवेयर में अपना काम पूरा करने के बाद मैं कुछ नहीं करता? @PJCHENder
इमरान पोलोब

1
@ImranPollob में कभी-कभी गलतियाँ हो जाती हैं। जब आप बहुत सारे कोड, ifs / elses / etc लिखते हैं। आप '`` वापसी के बाद भूल सकते हैं () `
Jone Polvora

46

next()कनेक्ट मिडलवेयर का हिस्सा है । राउटर प्रवाह के लिए कॉलबैक आपको परवाह नहीं करता है यदि आप अपने कार्यों से कुछ भी वापस करते हैं, तो return next()और next(); return;मूल रूप से समान है।

यदि आप उन कार्यों के प्रवाह को रोकना चाहते हैं जिन्हें आप next(err)निम्न की तरह उपयोग कर सकते हैं

app.get('/user/:id?', 
    function(req, res, next) { 
        console.log('function one');
        if ( !req.params.id ) 
            next('No ID'); // This will return error
        else   
            next(); // This will continue to function 2
    },
    function(req, res) { 
        console.log('function two'); 
    }
);

next()आपके अनुरोधों के मिडलवेयर का विस्तार करने के लिए बहुत अधिक उपयोग किया जाता है।


1
हम जैसे पैरामीटर भेज सकते हैं: next('No ID')?
अमोल एम कुलकर्णी

7
next('No ID')वास्तव में एक त्रुटि भेज रहा है, जो प्रवाह को तोड़ देगा।
drinchev

अगले का उपयोग करें (अशक्त, "somevalue"); Async.waterfall जैसे उपकरणों के लिए यह अगले फ़ंक्शन के लिए मान पारित करेगा। डेटा द्वारा संचालित इंटरैक्शन की जटिल श्रृंखला के लिए, मैं आमतौर पर फ़ंक्शन के बीच एक संदर्भ ऑब्जेक्ट पास करता हूं। इस तरह मैं जेनेरिक फ़ंक्शंस बना सकता हूं, जिन्हें कई अंत बिंदुओं पर साझा किया जा सकता है और संदर्भ में डेटा के माध्यम से प्रवाह को नियंत्रित कर सकता है
चाड विल्सन

5
"इसलिए अगला () और अगला (); वापसी; मूल रूप से समान है।" - बस मुझे जो पढ़ना था। thx @drinchev
निक

1
मैं विपरीत का निरीक्षण करता हूं (जब फायरिंग त्रुटि): अगला (त्रुटि) अगले मिडलवेयर को ट्रिगर करता है, लेकिन कोड निष्पादित करना जारी रखता है; अगला (त्रुटि) वापस अगले मिडलवेयर पर निष्पादन को फिर से लागू करता है। अगला (ई) और अगला (ई) एक ही नहीं हैं।
निकोलोडन

0

इसका उपयोग नहीं करना सबसे अच्छा है! मैं समझाता हूं, और यही मैं इसकी व्याख्या भी करता हूं।

अगला () फ़ंक्शन जिसमें कोई भी नाम हो सकता है और कन्वेंशन द्वारा अगले पर सेट किया गया है। यह अप्रत्यक्ष रूप से संचालन (PUT, GET, DELETE, ...) से संबंधित है जो आमतौर पर उदाहरण के लिए एक ही URI संसाधन पर किए जाते हैं/ user /: id

app.get('/user/:id', function (req,res,next)...)
app.put('/user/:id', function (req,res,next)...)
app.delete('/user/:id', function (req,res,next)...)
app.post('/user/', function ()...)

अब यदि आप app.get, app.put और app.delete को देखते हैं तो उसी uri (/ user /: id) का उपयोग करते हैं, केवल एक चीज जो उन्हें अलग करती है, वह है उनका कार्यान्वयन। जब अनुरोध किया जाता है (req) एक्सप्रेस req को पहले app.get में डालता है, यदि आपके द्वारा बनाया गया कोई सत्यापन क्योंकि वह अनुरोध उस नियंत्रक के लिए नहीं है, तो यह req को app.put को पास कर देता है, जो कि अगली फ़ाइल te file में है। पर। जैसा कि नीचे दिए गए उदाहरण में देखा गया है।

    app.get('/user/:id', function (req,res,next){

    if(req.method === 'GET')
    //whatever you are going to do
    else
      return next() //it passes the request to app.put

    //Where would GET response 404 go, here? or in the next one. 
    // Will the GET answer be handled by a PUT? Something is wrong here.

   })
    app.put('/user/:id', function (req,res,next){

    if(req.method === 'PUT')
    //whatever you are going to do
    else
      return next()

   })

समस्या यह है, कि अंत में आप सभी नियंत्रकों के लिए अनुरोध पास करना समाप्त करते हैं, यह उम्मीद करते हैं कि एक वही है जो आप चाहते हैं, जो कि रीक के सत्यापन के माध्यम से होता है। अंत में सभी नियंत्रक कुछ ऐसा प्राप्त करते हैं जो उनके लिए नहीं है :(।

तो, अगली () की समस्या से कैसे बचें ?

उत्तर वास्तव में सरल है।

1- संसाधन की पहचान करने के लिए केवल एक यूआरआई होना चाहिए

http: // IpServidor / colection /: resource / colection /: संसाधन यदि आपका URI इससे अधिक लंबा है, तो आपको एक नया uri बनाने पर विचार करना चाहिए

उदाहरण http: // IpServidor / उपयोगकर्ताओं / पेपे / संपर्क / contacto1

2-इस संसाधन पर सभी क्रियाओं को क्रियाओं की मूर्खता का सम्मान करते हुए किया जाना चाहिए http (get, post, put, delete, ...) इसलिए URI को कॉल करना वास्तव में कॉल करने का केवल एक तरीका है

POST http://IpServidor/users/  //create a pepe user 
GET http://IpServidor/users/pepe  //user pepe returns   
PUT http://IpServidor/users/pepe  //update the user pepe 
DELETE http://IpServidor/users/pepe  //remove the user pepe

अधिक जानकारी [ https://docs.microsoft.com/es-es/azure/altecture/best-practices/api-design#organize-the-api-around-resourcesearch1]

कोड देखते हैं! ठोस कार्यान्वयन जो हमें अगले () के उपयोग से बचाता है!

फ़ाइल इंडेक्स में। js

//index.js the entry point to the application also caller app.js
const express = require('express');
const app = express();

const usersRoute = require('./src/route/usersRoute.js');

app.use('/users', usersRoute );

फ़ाइल में userRoute.js

    //usersRoute.js
    const express = require('express');
    const router = express.Router();

    const getUsersController = require('../Controllers/getUsersController.js');
    const deleteUsersController = require('../Controllers/deleteUsersController.js');

    router.use('/:name', function (req, res) //The path is in /users/:name
    {
    switch (req.method)
    {
    case 'DELETE':
      deleteUsersController(req, res);
      break;
    case 'PUT':
     // call to putUsersController(req, res);
     break;
    case 'GET':
     getUsersController(req, res);
     break;
    default:
     res.status(400).send('Bad request');
    } });

router.post('/',function (req,res) //The path is in /users/
{
    postUsersController(req, res);
});

module.exports = router;

अब userRoute.js फ़ाइल वह करता है जो कि userRoute नामक एक फाइल को करने की अपेक्षा की जाती है, जो कि URI / उपयोगकर्ताओं / के मार्गों का प्रबंधन करना है।

// फ़ाइल getUserController.js

//getUsersController.js
    const findUser= require('../Aplication/findUser.js');
    const usersRepository = require('../Infraestructure/usersRepository.js');

    const getUsersController = async function (req, res)
    {

       try{
          const userName = req.params.name;
        //...
          res.status(200).send(user.propertys())

        }catch(findUserError){
           res.status(findUserError.code).send(findUserError.message)
        }
    }
   module.exports = getUsersController;

इस तरह आप अगले के उपयोग से बचते हैं, आप कोड को कम कर देते हैं, आप प्रदर्शन में लाभ प्राप्त करते हैं, आप SOLID का विकास करते हैं, आप माइक्रोसर्विस के लिए संभावित प्रवास के लिए दरवाजा खुला छोड़ देते हैं और सबसे ऊपर, प्रोग्रामर द्वारा पढ़ना आसान होता है।


2
यह गलत है, app.get आपके सुझाव के अनुसार app.put को पास नहीं करेगा। केवल मिलान अनुरोधों को प्राप्त किया जाता है यदि विधि केवल GET है। एप्लिकेशन मिडवेयर को कहा जाएगा। मिडलवेयर को अनुरोध विधि की जांच करने की आवश्यकता नहीं है। आपका सुझाव एक्सप्रेस के एक प्राथमिक कार्य को अनदेखा करता है और इसके बजाय आपकी स्वयं की रूटिंग को लागू करता है। इसके अलावा, आपका सुझाव मानता है कि मार्ग ही एकमात्र मिडलवेयर है जिसका आप उपयोग कर रहे हैं क्योंकि यह कभी भी कहीं भी नहीं जाता है।
रेवनेक्स

गलत जानकारी, कृपया उपरोक्त उत्तर देखें।
डीडीयामंड

-3

आगे() :

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

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