2012-02-14 10 views
21

मैं कनेक्ट/Express.js के साथ एक नोड.जेएस ऐप बना रहा हूं और मैं मूल रेंडर फ़ंक्शन पर अग्रेषित करने से पहले कुछ कोड चलाने के लिए res.render (view, विकल्प) फ़ंक्शन को अवरुद्ध करना चाहता हूं।Node.js/Express.js - Res.render फ़ंक्शन को ओवरराइड/अवरुद्ध कैसे करें?

app.get('/someUrl', function(req, res) { 

    res.render = function(view, options, callback) { 
     view = 'testViews/' + view; 
     res.prototype.render(view, options, callback); 
    }; 

    res.render('index', { title: 'Hello world' }); 
}); 

यह एक प्रत्याशित उदाहरण की तरह दिखता है, लेकिन यह एक समग्र रूपरेखा में फिट है जो मैं बना रहा हूं।

जावास्क्रिप्ट पर ओओपी और प्रोटोटाइप विरासत का मेरा ज्ञान थोड़ा कमजोर है। मैं ऐसा कुछ कैसे करूं?


अद्यतन: कुछ प्रयोग मैं निम्नलिखित के साथ आया था के बाद:

app.get('/someUrl', function(req, res) { 

    var response = {}; 

    response.prototype = res; 

    response.render = function(view, opts, fn, parent, sub){ 
     view = 'testViews/' + view; 
     this.prototype.render(view, opts, fn, parent, sub); 
    }; 

    response.render('index', { title: 'Hello world' }); 
}); 

यह काम करने के लिए लगता है। सुनिश्चित नहीं है कि यह सबसे अच्छा समाधान है क्योंकि मैं प्रत्येक अनुरोध के लिए एक नई प्रतिक्रिया रैपर ऑब्जेक्ट बना रहा हूं, क्या यह एक समस्या होगी?

+1

सामान्यतः यह है कि आप इसे कैसे करते हैं। यदि आप इसे एक मिडलवेयर में डालते हैं जिसका उपयोग राउटर से पहले किया जाता है तो आप इसे एक ही स्थान पर सेट कर सकते हैं। –

+0

मैंने मिडलवेयर का उपयोग करने के बारे में सोचा। निश्चित नहीं है कि मैं पूरे आवेदन के लिए प्रतिक्रिया व्यवहार को ओवरराइड करना चाहता हूं, केवल मेरे ढांचे के माध्यम से अनुरोध किए गए अनुरोधों के लिए। –

उत्तर

22

पुराना सवाल है, लेकिन अपने आप पूछ पाया वही चीज। Res रेंडर कैसे रोकें? अब एक्सप्रेस 4.0x का उपयोग कर कुछ।

आप मिडलवेयर का उपयोग/लिख सकते हैं। अवधारणा पहली बार मेरे लिए थोड़ा मुश्किल थी, लेकिन कुछ पढ़ने के बाद यह थोड़ा और समझ में आया। और बस इसे पढ़ने के लिए किसी भी संदर्भ के लिए, res.render ओवरराइड करने के लिए प्रेरणा वैश्विक दृश्य चर प्रदान करना था। मैं अपने सभी टेम्पलेट्स में उपलब्ध होने के लिए session चाहता हूं बिना मुझे हर res ऑब्जेक्ट में टाइप करना।

बुनियादी मध्यम प्रारूप प्रारूप है।

app.use(function(req, res, next) { 
    //.... 
    next(); 
}); 

अगला पैरा और फ़ंक्शन कॉल निष्पादन के लिए महत्वपूर्ण हैं। next कॉलबैक फ़ंक्शन है, कई मिडलवेयर को अवरुद्ध किए बिना अपनी चीज़ करने की अनुमति देने के लिए। बेहतर explanation read here

यह तो इस्तेमाल किया जा सकता एक ओवरराइड करने के लिए के लिए तर्क

app.use(function(req, res, next) { 
    // grab reference of render 
    var _render = res.render; 
    // override logic 
    res.render = function(view, options, fn) { 
     // do some custom logic 
     _.extend(options, {session: true}); 
     // continue with original render 
     _render.call(this, view, options, fn); 
    } 
    next(); 
}); 

प्रस्तुत करना मैं इस कोड परीक्षण किया है, एक्सप्रेस 3.0.6 का उपयोग कर। इसे बिना किसी मुद्दे के 4.x के साथ काम करना चाहिए। तुम भी

app.use('/myspcificurl', function(req, res, next) {...}); 
+0

क्या यह हर अनुरोध पर फ़ंक्शन को ओवरराइड करता है, जीसी पर दबाव डालता है? प्रोटोटाइप को ओवरराइड करने के लिए क्या अधिक समझदारी होगी? – jocull

+0

यह हर अनुरोध पर ओवरराइड करता है। यह संपत्ति छाया के माध्यम से प्रोटोटाइप ओवरराइड होगा। यदि आप चाहते हैं तो प्रोटोटाइप को ओवरराइड कर सकते हैं, लेकिन आम तौर पर आप मुख्य वस्तु पर गुणों को प्रोटोटाइप श्रृंखला में गहरा नहीं चाहते हैं। इस समय संपत्ति की तलाश तेज है। – Lex

+1

मुझे पहले यह जवाब नहीं मिला, लेकिन मेरे आस-पास झुकाव के बाद, अब मुझे यह मिल गया है। आप https://github.com/mettamage/renderExtMiddleware पर लेक्स के अपने कोड की एक भिन्नता जांच सकते हैं - मैं '_.extend (args)' का उपयोग नहीं करता हूं। मेरा कोड एक सामान्य दृश्य प्रस्तुत करता है * को छोड़कर * जब ग्राहक ब्राउज़र नहीं होता है, तो यह जेसन लौटाता है। –

7

response ऑब्जेक्ट में प्रोटोटाइप नहीं है। यह काम करना चाहिए (एक मिडलवेयर में डालने की रयान के विचार लेने):

var wrapRender = function(req, res, next) { 
    var _render = res.render; 
    res.render = function(view, options, callback) { 
    _render.call(res, "testViews/" + view, options, callback); 
    }; 
}; 

हालांकि, यह बेहतर हो सकता है ServerResponse.prototype हैक करने:

var express = require("express") 
    , http = require("http") 
    , response = http.ServerResponse.prototype 
    , _render = response.render; 

response.render = function(view, options, callback) { 
    _render.call(this, "testViews/" + view, options, callback); 
}; 
+0

इसके लिए धन्यवाद। हालांकि ऐसा लगता है कि यह लेआउट/मास्टर व्यू के साथ-साथ यह कैसे दिखता है, यह 'testViews/layout.ejs' को देखने का प्रयास करता है। मैंने स्रोत को देखा और देखा कि प्रतिक्रिया ऑब्जेक्ट पर _render विधि पहले ही परिभाषित है, क्या इससे समस्याएं पैदा हो सकती हैं? –

+0

हां, यह सही है - यह सभी विचारों के लिए "testViews /" को प्रीपेड करेगा। इसका 'ServerResponse._render' से कोई लेना देना नहीं है। आप क्या खत्म करने की कोशिश कर रहे हैं? –

+0

ServerRespone.prototype हैक को लागू करने का प्रयास किया और विफल रहा। मान लें कि यह नोड 0.6/एक्सप्रेस 2 में काम करता है? क्या आपको कोई विचार है कि इस काम को नोड 0.8 और कैसे 3 में बनाना है? –

6

यह एक अच्छा विचार है क्योंकि मिडलवेयर प्रत्येक अनुरोध और प्रत्येक के लिए निष्पादित हो रहा है उनमें से प्रत्येक उदाहरण के लिए एक प्रतिक्रिया या अनुरोध विधि ओवरराइड करने के लिए एक मध्यस्थ के उपयोग करने के लिए नहीं है के साथ उन विशेष URL कॉम्बो ओवरराइड कर सकते हैं समय कहा जाता है कि आप सीपीयू के साथ ही स्मृति का उपयोग करते हैं क्योंकि आप एक नया फ़ंक्शन बना रहे हैं।

जैसा कि आप जानते हैं कि जावास्क्रिप्ट प्रोटोटाइप-आधारित भाषा है और प्रत्येक ऑब्जेक्ट में प्रोटोटाइप होता है, जैसे प्रतिक्रिया और अनुरोध ऑब्जेक्ट्स। कोड देखकर (एक्सप्रेस 4.13।4) आप अपने प्रोटोटाइप पा सकते हैं: जब आप एक प्रतिक्रिया यह बहुत ज्यादा बेहतर यह प्रोटोटाइप के रूप में यह एक बार किया है ओवरराइड करने के लिए के हर एक उदाहरण के लिए एक विधि ओवरराइड करना चाहते

req => express.request 
res => express.response 

तो हर मामले में उपलब्ध है प्रतिक्रिया की:

var app = (global.express = require('express'))(); 
var render = express.response.render; 
express.response.render = function(view, options, callback) { 
    // desired code 
    /** here this refer to the current res instance and you can even access req for this res: **/ 
    console.log(this.req); 
    render.apply(this, arguments); 
}; 
+1

मुझे नहीं पता कि यह टिप्पणी स्वीकार्य क्यों नहीं है! यह सही सही जवाब है! –

3

मैं हाल ही में अपने आप को एक ही बात करने के लिए, मेरे टेम्पलेट से प्रत्येक के लिए एक विन्यास विशिष्ट Google Analytics प्रॉपर्टी आईडी और कुकी डोमेन प्रदान करने के लिए की आवश्यकता होगी, मिल गया।

यहां कई शानदार समाधान हैं।

मैंने लेक्स द्वारा प्रस्तावित समाधान के बहुत करीब के साथ जाना चुना, लेकिन उन समस्याओं में भाग गया जहां res.render() को कॉल करने से पहले ही मौजूदा विकल्प शामिल नहीं थे। उदाहरण के लिए, निम्नलिखित कोड एक अपवाद कॉल में विस्तार करने के लिए(), पैदा कर रहा था क्योंकि विकल्प अपरिभाषित गया था:

return res.render('admin/refreshes'); 

मैं जोड़ा निम्नलिखित है, जो विभिन्न तर्कों की कॉलबैक सहित कि संभव हो रहे हैं संयोजन, के लिए खातों । दूसरों द्वारा प्रस्तावित समाधानों के साथ एक समान दृष्टिकोण का उपयोग किया जा सकता है।

app.use(function(req, res, next) { 
    var _render = res.render; 
    res.render = function(view, options, callback) { 
    if (typeof options === 'function') { 
     callback = options; 
     options = {}; 
    } else if (!options) { 
     options = {}; 
    } 
    extend(options, { 
     gaPropertyID: config.googleAnalytics.propertyID, 
     gaCookieDomain: config.googleAnalytics.cookieDomain 
    }); 
    _render.call(this, view, options, callback); 
    } 
    next(); 
}); 

संपादित करें: बाहर कर देता है, एक काफी सरल तरीके से पूरा करने के लिए मुझे क्या करना कोशिश कर रहा था वहाँ, जबकि यह सब काम हो सकता है जब मैं वास्तव में कुछ कोड को चलाने के लिए आवश्यक है। मैंने फिर से एक्सप्रेस के लिए स्रोत और दस्तावेज़ों पर देखा, और यह पता चला कि ऐप.लोकल्स का उपयोग प्रत्येक टेम्पलेट को प्रस्तुत करने के लिए किया जाता है। तो मेरे मामले में, मैंने अंततः निम्नलिखित असाइनमेंट के साथ सभी मिडलवेयर कोड को प्रतिस्थापित कर दिया:

app.locals.gaPropertyID = config.googleAnalytics.propertyID; 
app.locals.gaCookieDomain = config.googleAnalytics.cookieDomain; 
+0

दो वास्तव में अच्छे अंक। स्थानीय संपत्ति ज्यादातर मामलों में फिट होगी। और यदि कॉलबैक प्रस्तुत करने के लिए कोई विकल्प पास नहीं किया जाता है, तो अपरिभाषित हो जाता है, और सभी नरक टूट जाते हैं। – Lex

संबंधित मुद्दे