2015-11-19 14 views
12

मैं अपनी परियोजना को थोड़ा सा साफ करना चाहता हूं और अब मैं अपने मार्गों के लिए es6 कक्षाओं का उपयोग करने की कोशिश करता हूं। मेरी समस्या यह है कि यह हमेशा अनिर्धारित है।नोडजेस, एएस 6 कक्षाओं के रूप में एक्सप्रेस मार्ग

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

class Routes { 
    constructor(){ 
     this.foo = 10 
    } 

    Root(req, res, next){ 
     res.json({foo: this.foo}); // TypeError: Cannot read property 'foo' of undefined 
    } 
} 

var routes = new Routes(); 
app.get('/', routes.Root); 
app.listen(8080); 

उत्तर

10

कोशिश this पिन करने के लिए कोड का उपयोग करें:

app.get('/', routes.Root.bind(routes)); 

आप बॉयलरप्लेट को रेखांकित bindAll समारोह का उपयोग कर से बाहर निकल सकते। उदाहरण के लिए:

var _ = require('underscore'); 

// .. 

var routes = new Routes(); 
_.bindAll(routes) 
app.get('/', routes.Root); 

मैंने यह भी पाया कि ES7 आप एक और अधिक सुरुचिपूर्ण ढंग से कोड लिखने की अनुमति देता है:

class Routes { 
    constructor(){ 
     this.foo = 10 
    } 

    Root = (req, res, next) => { 
     res.json({foo: this.foo}); 
    } 
} 

var routes = new Routes(); 
app.get('/', routes.Root); 
+1

ES7 जब तक यहाँ हो जाता है - मैं _.bindAll प्यार मैं इसके बारे में पूरी तरह से अनजान था। यह हर रूट में उपयोगकर्ताओं को बाध्य करने से कहीं ज्यादा अच्छा है! –

5

क्योंकि आप एक स्टैंडअलोन समारोह व्यक्त करने के लिए के रूप में एक विधि उत्तीर्ण कर ली है यह क्या हो रहा है । एक्सप्रेस उस वर्ग के बारे में कुछ भी नहीं जानता है, जो यह आता है, इसलिए यह नहीं पता कि आपकी विधि कहां से this के रूप में उपयोग करने के लिए कौन सा मान उपयोग करना है।

आप के मान को bind के साथ मजबूर कर सकते हैं।

app.get('/', routes.Root.bind(routes)); 

या आप मार्गों के प्रबंधन के लिए वैकल्पिक निर्माण का उपयोग कर सकते हैं। आप कक्षाओं के बिना ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के लिए अभी भी बहुत सारे सिंटैक्टिक लाभों का उपयोग कर सकते हैं।

function Routes() { 
    const foo = 10; 

    return { 
    Root(req, res, next) { 
     res.json({ foo }); 
    } 
    }; 
} 

const routes = Routes(); 
app.get('/', routes.Root); 
app.listen(8080); 
  • आप this
  • के मूल्य के बारे में चिंता करने की यह कोई फर्क नहीं पड़ता समारोह new या नहीं
  • साथ कहा जाता है कि क्या आप पर bind बुला की जटिलता से बच सकते हैं नहीं होगा प्रत्येक मार्ग

संसाधनों की एक अच्छी सूची here है, क्यों ईएस 6 कक्षाएं उतनी अच्छी नहीं हैं जितनी वे लग सकती हैं।

2

उपरोक्त उत्तरों जटिल पर थोड़ा सा प्रतीत होता है। चेकआउट मैं यहाँ क्या किया है:

class Routes { 
    constructor(req, res, next) { 
    this.req = req; 
    this.res = res; 
    this.next = next; 
    this.foo = "BAR" 
    // Add more data to this. here if you like 
    } 

    findAll(){ 
    const {data, res,} = this; // Or just reference the objects directly with 'this' 
    // Call functions, do whaterver here... 
    // Once you have the right data you can use the res obejct to pass it back down 

    res.json ({foo: this.foo}); // Grabs the foo value from the constructor 

    } 
} 

अब जब यह इस वर्ग का उपयोग कर की बात आती है तो आप इस की तर्ज पर कुछ कर सकते हैं:

var express = require('express'); 
var router = express.Router(); 
var {Routes} = require('./Routes'); 

router.get('/foo', (req, res, next) => { 
    new Routes(req, res, next).findAll(); 
}); 

मैं दो फ़ाइलों अलग होता है, ताकि आप बस Routes कक्षा को अपने Router फ़ाइल में आवश्यकता है।

आशा है कि इससे मदद मिलेगी!

+0

स्वीकार्य उत्तर से यह बहुत अधिक जटिल लगता है। इसके लिए आपको रिक, रेस, और अगले() के लिए अपनी कक्षा के निजी सदस्य होने की आवश्यकता है। ये वर्ग के सदस्य वास्तव में केवल मिडलवेयर फ़ंक्शन हैं जिन्हें वांछित एक्सप्रेस मिडलवेयर प्रकार के समान हस्ताक्षर प्रदान करने की आवश्यकता होती है। '.bind' विधि का उपयोग इस डिजाइन विचार के लिए सबसे अच्छा समाधान है। एक नोट के रूप में, मैं इसे टाइपस्क्रिप्ट में कर रहा हूं और लगता है कि यह बहुत अच्छा काम कर रहा है। –

1

या यदि आप प्रति मार्ग संदर्भ बाध्यकारी पसंद नहीं करते हैं, तो आप इसे वैकल्पिक रूप से अपने वर्ग के निर्माता में विधियों के साथ बाध्य कर सकते हैं।

उदा:

constructor() { 
    this.foo = 10; 
    this.Root = this.Root.bind(this); 
} 
संबंधित मुद्दे