এক্সপ্রেসে ব্যবহৃত "পরবর্তী" প্যারামিটারটি কী?


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
না, আপনার এক্সপ্রেস.জেএস ডকুমেন্টেশনের এই অংশটি উল্লেখ করা উচিত: expressjs.com/guide.html# পাসিং- ক্রোটি নিয়ন্ত্রণ
ডমিনিক বার্নস

3
মূলত, পরবর্তী চলমান রুটটি অনুরোধের URL টির সাথে মিলবে one এই ক্ষেত্রে, যদি অন্য কোনও রুটের মাধ্যমে নিবন্ধভুক্ত হয় 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অ্যাসিঙ্ক সহ একটি মডেল ধরে আমি এইরকম প্রদর্শিত উদাহরণটি মডেল করতে চাইছি 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');
});

আশা করি এটি আপনাকে কিছুটা অনুপ্রেরণা দিয়েছে!


তুমি এটা বলতে পারতে! আমি রুট মিডলওয়্যারগুলির সাথে এই ধরণের জিনিসটি করতে আরও আগ্রহী হব , যদিও এটি কোনও নির্দিষ্ট রুটের ক্রম বা নির্দিষ্ট ইউআরআই কাঠামোর সাথে যুক্তি যুক্ত করে না।
আশেরাহ

5
কেন কখনও কখনও আপনি পরের দিকে ফিরে যান () তবে কখনও কখনও যান না
জন

6
@ জন: রিটার্ন মানটি আসলে উপেক্ষা করা হয়েছে; আমি আর কল করব না তা নিশ্চিত করার জন্য আমি সেখানে ফিরে আসতে চাইছি next()। যদি আমি স্রেফ ব্যবহার করি তবে এটি একই হবে next(new Error(…)); return;
আশেরাহ

1
@ স্তর0: প্রত্যাবর্তনের মান উপেক্ষা করা হবে; আপনি এটি সংক্ষিপ্ত বিবেচনা করতে পারেন next(new Error(…)); return;। আমরা যদি একটি মান পাস next, এটা একতরফা একটি ত্রুটি বিবেচিত হচ্ছে । আমি এক্সপ্রেস কোডটি খুব বেশি লক্ষ্য করি নি, তবে চারপাশে খনন করি এবং আপনার যা প্রয়োজন তা পেয়ে যাবেন :)
আশেরাহ

1
@ level0: (i পরিবর্তন করেছি 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আপনার কাছে নোডে অনুরোধ-প্রতিক্রিয়া চক্র সম্পর্কে কিছুটা ধারণা থাকা দরকার যদিও বিস্তারিত কিছু নয়। এটি আপনাকে কোনও নির্দিষ্ট সংস্থার জন্য এইচটিটিপি অনুরোধ করার মাধ্যমে শুরু হয় এবং আপনি যখন ব্যবহারকারীর কাছে কোনও প্রতিক্রিয়া ফেরৎ পাঠান তখনই যখন আপনি রেজ.সেন্ড ('হ্যালো ওয়ার্ল্ড') এর মতো কোনও সমস্যার মুখোমুখি হন;

আসুন একটি খুব সহজ উদাহরণ দেখুন।

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

এখানে আমাদের পরবর্তী () দরকার নেই, কারণ রেস.সেন্ড চক্রটি শেষ করবে এবং নিয়ন্ত্রণটি পুনরায় মিডলওয়্যারের কাছে হস্তান্তর করবে।

এবার আসুন আরেকটি উদাহরণ দেখুন।

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

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

এখানে একই পথের জন্য আমাদের কাছে মিডলওয়্যার দুটি ফাংশন রয়েছে। তবে আপনি সর্বদা প্রথমটির কাছ থেকে প্রতিক্রিয়া পাবেন। কারণ মিডলওয়্যার স্ট্যাকের মধ্যে এটি প্রথমে মাউন্ট করা হয়েছে এবং রেস.সেন্ডটি চক্রটি শেষ করবে।

তবে যদি আমরা সবসময় "হ্যালো ওয়ার্ল্ড !!!!" না চাই প্রতিক্রিয়া ফিরে। কিছু শর্তের জন্য আমরা "হ্যালো প্ল্যানেট !!!!" চাই প্রতিক্রিয়া। আসুন উপরের কোডটি পরিবর্তন করুন এবং দেখুন কী ঘটে।

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এখানে কি করছে? এবং হ্যাঁ আপনি অনুমান করতে পারেন। কন্ডিশনটি সত্য হলে এটি প্রথম মিডলওয়্যার ফাংশনটি এড়িয়ে যাবে এবং পরবর্তী মিডলওয়্যার ফাংশনটি আহ্বান করবে এবং আপনার "Hello Planet !!!!"প্রতিক্রিয়া হবে।

সুতরাং, মিডলওয়্যার স্ট্যাকের পরবর্তী ফাংশনে নিয়ন্ত্রণটি পাস করুন।

প্রথম মিডওয়্যার ফাংশনটি যদি কোনও প্রতিক্রিয়া ফিরে না পাঠায় তবে একটি যুক্তি প্রয়োগ করে এবং তারপরে আপনি দ্বিতীয় মিডলওয়্যার ফাংশন থেকে প্রতিক্রিয়া ফিরে পান What

নীচের মত কিছু: -

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কল যে একই ফাঁসি গাছে কোড ছিল ... Guess আমি সবসময় শুধু, হাহ এক্সপ্রেস চেক করতে পারেন? / তার পাঠ্য সম্পাদককে রান করে;)
রাফিন

@ আরফিন হ্যাঁ আপনি পরের বারের মতো গোটোর কথা ভাবতে পারেন তবে এরপরে জানেন যে কোথায় যেতে হবে তার বিপরীতে যেখানে একটি লেবেল প্রয়োজন। পরবর্তীটি পরবর্তী মিডলওয়্যার ফাংশনে নিয়ন্ত্রণটি পাস করবে। এছাড়াও, আপনি নিজের পছন্দ মতো যে কোনও কিছু 'নেক্সট' রাখতে পারেন। এটি এখানে কেবল একটি লেবেল। তবে সেরা অনুশীলনটি হ'ল 'পরের' নামটি ব্যবহার করুন
মাভ 55

3
ঠিক আছে, দেখে মনে হচ্ছে এটি সঠিক নয়। আমি কোড (চেষ্টা pastebin এখানে ), এবং পরে কোড next()কল বলা হয় । এই ক্ষেত্রে, past the next() callকনসোলে লেখা হয়, এবং তারপরে আমি একটি Error: Can't set headers after they are sent.ত্রুটি পাই , যেমন দ্বিতীয় res.sendবলা হয়, যদিও ব্যর্থ হয়। কোড প্রবাহ কল হওয়ার পরে ফিরে আসেnext() , যা @ আশের returns(বা অন্যান্য যুক্তি পরিচালনা) গুরুত্বপূর্ণ করে তোলে ।
ruffin

4
@ আরফিন, হ্যাঁ আপনি ঠিক বলেছেন। next()অবশিষ্ট বিবৃতিগুলির কার্যকারিতা এড়াতে আমাদের রিটার্ন বিবৃতি প্রয়োজন । যে নির্দেশ করার জন্য ধন্যবাদ।
মাভা 55

1
"মিডলওয়্যার" কী / ডাব্লু / স্পষ্ট উদাহরণগুলি বোঝানোর জন্য এবং কেবলমাত্র ডকুমেন্টেশনকে তোতা দেওয়ার জন্য ধন্যবাদ দেওয়ার জন্য আপনাকে ধন্যবাদ। এটিই একমাত্র উত্তর যা ঘটেছিল, কেন এবং কীভাবে তা সম্পর্কে পরিষ্কার কিছু বলে।
এমসি

11

পরবর্তীটি পরবর্তী মিডলওয়্যার ফাংশনে নিয়ন্ত্রণ পাস করতে ব্যবহৃত হয়। না হলে অনুরোধটি ফাঁসি বা খোলা থাকবে।


6
আমি নিশ্চিত না যে এই উত্তরটি প্রায় সাত বছরের পুরানো প্রশ্নে কী যুক্ত করে ...
মেরজিগ

সংক্ষিপ্ত হলেও, এই মন্তব্যটি আমাকে এ দিকে নিয়ে যায়: এক্সপ্রেশনস /en/guide/writing-middleware.html
hmak

@ মেহেরজিগ, এটি একটি লাইনার এবং এটি সমস্ত কিছু কভার করে
এম গোপাল ২

5

এই ফাংশনটি কল করা অ্যাপ্লিকেশনটিতে পরবর্তী মিডলওয়্যার ফাংশনটি আহ্বান করে। পরবর্তী () ফাংশনটি নোড.জেএস বা এক্সপ্রেস এপিআইয়ের অংশ নয়, তবে এটি তৃতীয় আর্গুমেন্ট যা মিডওয়্যার ফাংশনে পাস করা হয়েছে। পরবর্তী () ফাংশনটির যেকোনও নাম দেওয়া যেতে পারে, তবে কনভেনশন অনুসারে এটি সর্বদা নাম রাখা হয় "পরবর্তী"।


2

nextফাংশনটি সম্পাদন করা সার্ভারকে জানিয়ে দেয় যে আপনি এই মিডলওয়্যার পদক্ষেপটি সম্পন্ন করেছেন এবং এটি চেইনের পরবর্তী পদক্ষেপটি কার্যকর করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.