एक्सप्रेस: ​​एक अलग फ़ाइल से मार्गों पर ऐप-इंस्टेंस कैसे पास करें?


103

मैं अपने मार्गों को अलग-अलग फ़ाइलों में विभाजित करना चाहता हूं, जहां एक फ़ाइल में सभी मार्ग और दूसरे में एक ही कार्रवाई होती है। वर्तमान में मेरे पास इसे प्राप्त करने के लिए एक समाधान है, हालांकि मुझे कार्यों में इसे एक्सेस करने में सक्षम होने के लिए ऐप-इंस्टेंस को वैश्विक बनाने की आवश्यकता है। मेरा वर्तमान सेटअप इस तरह दिखता है:

app.js:

var express   = require('express');
var app       = express.createServer();
var routes    = require('./routes');

var controllers = require('./controllers');
routes.setup(app, controllers);

app.listen(3000, function() {
  console.log('Application is listening on port 3000');
});

routes.js:

exports.setup = function(app, controllers) {

  app.get('/', controllers.index);
  app.get('/posts', controllers.posts.index);
  app.get('/posts/:post', controllers.posts.show);
  // etc.

};

नियंत्रक / index.js:

exports.posts = require('./posts');

exports.index = function(req, res) {
  // code
};

नियंत्रक / posts.js:

exports.index = function(req, res) {
  // code
};

exports.show = function(req, res) {
  // code
};

हालाँकि, इस सेटअप में एक बड़ा मुद्दा है: मेरे पास एक डेटाबेस है और एक ऐप-इंस्टेंस है, जिसे मुझे क्रियाओं (नियंत्रकों / *। Js) में पास करने की आवश्यकता है। एकमात्र विकल्प जिसके बारे में मैं सोच सकता था, वह दोनों चर को वैश्विक बना रहा है जो वास्तव में कोई समाधान नहीं है। मैं मार्गों को कार्यों से अलग करना चाहता हूं क्योंकि मेरे पास बहुत सारे मार्ग हैं और उन्हें केंद्रीय स्थान पर रखना चाहता हूं।

क्रियाओं के लिए चर पास करने का सबसे अच्छा तरीका क्या है लेकिन मार्गों से कार्यों को अलग करना है?


आपके नियंत्रकों को कैसे दिखता है? हो सकता है कि आप इसे एक वस्तु के बजाय एक फ़ंक्शन बना सकते हैं जो पैरामीटर प्राप्त कर सकते हैं।
मिहई

आवश्यकता ('नियंत्रकों') के लिए नियंत्रकों / index.js की आवश्यकता होती है। हालाँकि, एक फ़ंक्शन काम नहीं करेगा क्योंकि मैं मार्गों में ऑब्जेक्ट का उपयोग करता हूं (मार्गों को देखें। js) और इस प्रकार यह तर्क नहीं दे सकता है, भले ही यह एक फ़ंक्शन हो।
क्लाउडियो अल्बर्टिन

जवाबों:


165

का उपयोग करें req.app,req.app.get('somekey')

कॉल करके बनाया गया एप्लिकेशन वेरिएबल express()रिक्वेस्ट और रिस्पॉन्स ऑब्जेक्ट पर सेट किया गया है।

देखें: https://github.com/visionmedia/express/blob/76147c78a15904d4e4e469095a29d1bec9775ab6/lib/express.js#L34-L35


धन्यवाद। मुझे लगता है कि यह app.set ('नाम', वैल) के साथ सेट किए गए चर तक पहुंचने का सबसे अच्छा तरीका है;
पावेल कोस्टेंको

4
भूलने के कॉल करने के लिए मत app.set('somekey', {})app.js में
ankitjaininfo

3
इस तरह के बारे में मेरी एकमात्र पकड़ हालांकि मुझे यह पसंद है कि यह तब होता है जब आप एक app.locals.authorized को चलाने की कोशिश कर रहे हैं जैसे कि (main.js में नहीं): app.route('/something').get(app.locals.authorized,function(req,res,next){});यह संभव नहीं है क्योंकि यह req गुंजाइश के बाहर है।
गाबियो

मैं अलग-अलग क्वेरी पैरामीटर के लिए अलग-अलग पासपोर्ट रणनीति का उपयोग कर रहा हूं। इसलिए मैं पासपोर्टवेयर ("रणनीति-नाम") को एक मिडलवेयर में सेट करने की कोशिश कर रहा हूं। यहां तक ​​कि अगर मैं उस पासपोर्ट में पासपोर्ट को केवल पासपोर्ट = req.app के साथ संग्रहीत करता हूं, तो ('पासपोर्ट') प्राप्त करें। यह अनुरोधों के एक और सेट के लिए संशोधित किया जा रहा है। ऐसा क्यों है ?
कार्तिकेय मिश्रा

अगर मैं ऐसा करता हूं, तो मेरे मामले में req ऑब्जेक्ट में रेडिस और db जैसे ऑब्जेक्ट इंस्टेंस होंगे। क्या यह अनुप्रयोग के प्रदर्शन को प्रभावित नहीं करेगा? उदाहरण के लिए: index.js app.set ('redis', redis_client) में; मार्गों में / example.js रूटर = आवश्यकता ('एक्सप्रेस')। राउटर (); route.get ( '/ परीक्षण', (अनुरोध, रेस, अगले) => {conosle.log (req.app.get ( 'redis')); वापसी res.send ( "// किया");})
सुजान अण्णा ने

101

Node.js परिपत्र निर्भरता का समर्थन करता है।
आवश्यकता ('./ मार्गों') (एप्लिकेशन) के बजाय परिपत्र निर्भरता का उपयोग करना बहुत सारे कोड को साफ करता है और प्रत्येक मॉड्यूल को इसकी लोडिंग फ़ाइल पर कम निर्भर करता है:


app.js

var app = module.exports = express(); //now app.js can be required to bring app into any file

//some app/middleware setup, etc, including 
app.use(app.router);

require('./routes'); //module.exports must be defined before this line


मार्गों / index.js

var app = require('../app');

app.get('/', function(req, res, next) {
  res.render('index');
});

//require in some other route files...each of which requires app independently
require('./user');
require('./blog');


----- 04/2014 अपडेट -----
एक्सप्रेस 4.0 ने एक्सप्रेस.रुटर () विधि जोड़कर मार्गों को परिभाषित करने के लिए usecase तय किया!
प्रलेखन - http://expressjs.com/4x/api.html#router

उनके नए जनरेटर से उदाहरण:
मार्ग लिखना:
https://github.com/expressjs/generator/blob/master/templates/js/routes/index.js
इसे ऐप में जोड़ना / नाम देना: https://github.com /expressjs/generator/blob/master/templates/js/app.js#L24

अन्य संसाधनों से एप्लिकेशन तक पहुंचने के लिए अभी भी usecases हैं, इसलिए परिपत्र निर्भरताएं अभी भी एक वैध समाधान हैं।


1
"यह फ़ाइल लोड करने पर कम निर्भर है" - यह इसकी लोडिंग फ़ाइल के विशिष्ट फ़ाइलपथ पर निर्भर है । यह बहुत तंग युग्मन है, तो चलो बहाना नहीं यह नहीं है।
कैमिलो मार्टिन

2
बस बहुत सावधान रहें (पढ़ें: पिछले एक घंटे से मैं जो संघर्ष कर रहा था, वह मत करो) कि ऐप को निर्यात करने के बादapp.js आपको रूटिंग फ़ाइल की आवश्यकता होगी । एक वास्तविक गड़बड़ के लिए परिपत्र कॉल कर सकते हैं, इसलिए सुनिश्चित करें कि आप जानते हैं कि वे कैसे काम करते हैं ! require()
नटोमामी

मुझे ईमानदारी से लगता है कि req.app.get ('somekey') का उपयोग करने के बारे में @Feng का जवाब वास्तव में सर्कुलर निर्भरता का उपयोग करने की तुलना में बेहतर और क्लीनर समाधान है।
क्लाउडियो मेजसलास्मा

@Green यदि ऐप खाली है, तो आपको एक ऐसी फ़ाइल की आवश्यकता है जो appBEFORE ऐप module.exportsको परिभाषित करे। आपको इंस्टेंट करना होगा app, सेट करना होगा module.exports, इसके बाद ऐसी फ़ाइलों की आवश्यकता हो सकती है, app लेकिन किसी भी तरह से, परिपत्र निर्भरता करना एक विरोधी पैटर्न है जिसे एक्सप्रेस ने हल किया है - आपको अब ऐसा करने की आवश्यकता नहीं होनी चाहिए।
विल स्टर्न

26

जैसा कि मैंने टिप्पणियों में कहा था, आप किसी फ़ंक्शन को मॉड्यूल.एक्सपोर्ट के रूप में उपयोग कर सकते हैं। एक फ़ंक्शन भी एक ऑब्जेक्ट है, इसलिए आपको अपना सिंटैक्स बदलने की आवश्यकता नहीं है।

app.js

var controllers = require('./controllers')({app: app});

controllers.js

module.exports = function(params)
{
    return require('controllers/index')(params);
}

नियंत्रक / index.js

function controllers(params)
{
  var app = params.app;

  controllers.posts = require('./posts');

  controllers.index = function(req, res) {
    // code
  };
}

module.exports = controllers;

क्या फ़ंक्शन के अंदर किसी ऑब्जेक्ट को वापस करना ठीक है या क्या यह बेहतर है ताकि आप अपने उदाहरण में तरीकों को सेट कर सकें?
क्लाउडियो अल्बर्टिन

मुझे लगता है कि या तो दृष्टिकोण ठीक है।
मिहाइ

क्योंकि मेरे पास बहुत सी विधियाँ हैं, मैं उन्हें प्रत्येक वस्तु के बजाय मैन्युअल रूप से सेट करना पसंद करूँगा। यह तब काम करेगा जब मैं सिर्फ ऑब्जेक्ट वापस कर दूंगा, लेकिन क्या कोई समाधान नहीं है जो थोड़ा सा चापलूसी है? मेरे वास्तविक तरीकों को दो बार प्रेरित किया जाएगा ...
क्लाउडियो अल्बर्टिन

यकीन नहीं होता अगर मैं तुम्हें समझ गया, लेकिन मुझे लगता है कि तुम उस controllersसमारोह के बाहर कार्यान्वयन को स्थानांतरित कर सकते हैं , कुछ इस तरह: jsfiddle.net/mihaifm/yV79K
mihai

नियंत्रकों / index.js को नियंत्रक var को वापस करने की आवश्यकता नहीं है?
यलम्बर

5

या बस ऐसा करें:

var app = req.app

मिडिलवेयर के अंदर आप इन मार्गों के लिए उपयोग कर रहे हैं। उसके जैसा:

router.use( (req,res,next) => {
    app = req.app;
    next();
});

कोई मुझे बताए कि यह स्वीकृत उत्तर क्यों नहीं है? निर्भरता के लिए आप app.use('my-service', serviceInstance)मुख्य राउटर और req.app.get('my-service')कंट्रोलर में @Feng
Felipe

0

मान लीजिए कि आपके पास "कॉनोलर्स" नाम का एक फ़ोल्डर है।

अपने app.js में आप यह कोड डाल सकते हैं:

console.log("Loading controllers....");
var controllers = {};

var controllers_path = process.cwd() + '/controllers'

fs.readdirSync(controllers_path).forEach(function (file) {
    if (file.indexOf('.js') != -1) {
        controllers[file.split('.')[0]] = require(controllers_path + '/' + file)
    }
});

console.log("Controllers loaded..............[ok]");

... तथा ...

router.get('/ping', controllers.ping.pinging);

आपके नियंत्रकों के लिए आपके पास इस कोड के साथ "ping.js" फ़ाइल होगी:

exports.pinging = function(req, res, next){
    console.log("ping ...");
}

और यह बात है ...।


0
  1. अपने डीबी ऑब्जेक्ट को सभी नियंत्रकों के लिए हर जगह इसे पारित करने के लिए सुलभ बनाने के लिए: एक एप्लिकेशन-स्तरीय मिडलवेयर बनाएं जो डीबी ऑब्जेक्ट को प्रत्येक आरक्यू ऑब्जेक्ट से जोड़ता है, फिर आप इसे प्रत्येक नियंत्रक में एक्सेस कर सकते हैं।
// app.js
let db = ...;  // your db object initialized
const contextMiddleware = (req, res, next) => {
  req.db=db;
  next();
};
app.use(contextMiddleware);
  1. हर जगह ऐप इंस्टेंस से बचने के लिए, इसके बजाय, मार्गों को पास करने के लिए जहां ऐप है
// routes.js  It's just a mapping.
exports.routes = [
  ['/', controllers.index],
  ['/posts', controllers.posts.index],
  ['/posts/:post', controllers.posts.show]
];

// app.js
var { routes }    = require('./routes');
routes.forEach(route => app.get(...route));
// You can customize this according to your own needs, like adding post request

अंतिम app.js:

// app.js
var express   = require('express');
var app       = express.createServer();

let db = ...;  // your db object initialized
const contextMiddleware = (req, res, next) => {
  req.db=db;
  next();
};
app.use(contextMiddleware);

var { routes }    = require('./routes');
routes.forEach(route => app.get(...route));

app.listen(3000, function() {
  console.log('Application is listening on port 3000');
});

एक और संस्करण: आप इसे अपनी आवश्यकताओं के अनुसार अनुकूलित कर सकते हैं, जैसे पोस्ट अनुरोध को जोड़ना

// routes.js  It's just a mapping.
let get = ({path, callback}) => ({app})=>{
  app.get(path, callback);
}
let post = ({path, callback}) => ({app})=>{
  app.post(path, callback);
}
let someFn = ({path, callback}) => ({app})=>{
  // ...custom logic
  app.get(path, callback);
}
exports.routes = [
  get({path: '/', callback: controllers.index}),
  post({path: '/posts', callback: controllers.posts.index}),
  someFn({path: '/posts/:post', callback: controllers.posts.show}),
];

// app.js
var { routes }    = require('./routes');
routes.forEach(route => route({app}));

-1

डेटाबेस के लिए डेटा एक्सेस सर्विस को अलग करें जो सभी डीबी को साधारण एपीआई के साथ काम करेगी और साझा स्थिति से बचेंगी।

अलग-अलग मार्ग।सेटअप ओवरहेड की तरह दिखता है। मैं इसके बजाय कॉन्फ़िगरेशन आधारित रूटिंग रखना पसंद करूंगा। और .json या एनोटेशन के साथ मार्गों को कॉन्फ़िगर करें।


डेटा एक्सेस सर्विस का क्या मतलब है? कैसा लगेगा?
क्लाउडियो अल्बर्टिन

मेरा असली मार्ग। Js फ़ाइल बहुत बड़ा है और एक्सप्रेस-नेमस्पेस मॉड्यूल का उपयोग करता है। आप कार्यों से मार्गों को कैसे अलग करेंगे?
क्लाउडियो अल्बर्टिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.