2016-11-22 11 views
1

初めてクラスを使用したいと思っていましたが、私は奇妙な問題に遭遇しています。すべてのクラスは正常に動作し、クラス変数の書き込み/読み込みは正常です。しかし、あるクラスはあまりうまくやっていません。es6クラスの変数を読み取ることができません(未定義のプロパティ '...'を読み取ることはできません)

TypeError: Cannot read property 'product' of undefined at getProducts (***/controllers/ProductController.js:41:13)

私はMEANスタックを使用して学校の割り当てのためのREST APIを書いている:

私は現在、このエラーを取得しています。

現在何が起こっているか要するに

index.js

// dependencies 
const Api = require('./routes/api') 

class Rest 
{ 
    constructor() 
    { 
     this.api = new Api() 
     this.init() 
    } 

    init() 
    { 
     ... // express server configuration 

     // routes 
     this.routes() 
    } 

    // set routes 
    routes() 
    { 
     app.use('/api', this.api.getRouter()) 
    } 
} 

new Rest() 

/routes/api.js

// dependencies 
const express = require('express') 
const Products = require('./api/products') 

class Api 
{ 
    constructor() 
    { 
     this.router = express.Router() 
     this.products = new Products() 
     this.routes() 
    } 

    getRouter() { return this.router } 

    routes() 
    { 
     // product routes 
     this.router.use('/products', this.products.getRouter()) 
    } 
} 


// return routes 
module.exports = Api 

ルート/ API/products.js

// dependencies 
const express = require('express') 
const productController = require('../../controllers/ProductController') 

class Product 
{ 
    constructor() 
    { 
     this.router = express.Router() 
     this.controller = new productController() 
     this.routes() 
    } 

    getRouter() { return this.router } 

    // set header options 
    setCollectionOptions(req, res, next) 
    { 
     res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') 
     next() 
    } 

    // set routes 
    routes() 
    { 
     this.router.route('/') 
      .options([this.setCollectionOptions, this.controller.getOptions]) 
      .get([this.setCollectionOptions, this.controller.getProducts]) 
    } 
} 

// return routes 
module.exports = Product 

モデル/ Product.js

// dependencies 
const mongoose = require('mongoose') 
const mongoosePaginate = require('mongoose-paginate') 

// create schema for model 
const productSchema = new mongoose.Schema({ 
    name: String, 
    sku: String, 
    price: String, 
    created_at: { type: String, default: Date.now }, 
    updated_at: { type: String, default: Date.now } 
}) 
productSchema.plugin(mongoosePaginate) 

// export model 
module.exports = mongoose.model('Products', productSchema) 

コントローラ/ ProductController.js

// dependencies 
const express = require('express') 

class ProductController 
{ 
    constructor() 
    { 
     this.product = require('../models/product') 
    } 


    getProducts(req, res, next) 
    { 
     this.product.find() // error occurs here! 
     ... // rest of the code 
    } 
} 

エラーは、私が設定した直後に、this.product.find()

I console.log(this.product)で発生しますそれはただ返します良い。しかし、私がhttp://localhost:port/api/productsでGETのページを要求すると、私はこのエラーを受け取ります。

また、ProductControllerでメソッドを使用しようとすると、同じエラーが発生します。例:

class ProductController 
{ 
    constructor() 
    { 
     this.product = require('../models/product') 
    } 

    init() 
    { 
     console.log('hi!') 
    } 

    getProducts(req, res, next) 
    { 
     this.init() 

     ... // rest of code 
    } 
} 

ありがとうございます。

答えて

2

routes/api/products.jsでは、メソッドを渡すだけです。つまり、呼び出されたときにはthisが設定されません。あなたは、例えば、それらをバインドする必要があります。

.get([this.setCollectionOptions.bind(this), this.controller.getProducts.bind(this.controller)]) 

または矢印関数を使用し、それは引数の数に注意を要するものの:

.get([(req, res, next) => this.setCollectionOptions(req, res, next), (req, res, next) => this.controller.getProducts(req, res, next)]) 

はに渡されるメソッドのためにこれを行うことを忘れないでください。 .optionsも。

+1

これを 'this.controller'にバインドする必要があります。たぶん、矢印機能は簡単な解決策です。 – Bergi

+0

@Bergi、ありがとう、受信機についての良いキャッチ。矢印の例も追加されました。 – Bakkot

+0

引数の数が分からないか、あまりにも多くの綴りがある場合は、rest/spread構文を使用することもできます: '(... args)=> this.controller.getProducts(... args) ' – Bergi

関連する問題