首页 > 解决方案 > 使用 Expressjs 和 mysql 的 API 的 MVC 模式`未定义不是函数`

问题描述

我正在使用 Node、Express、MySQL 构建 API 端点,简化如下,当访问/orders路由时,API 崩溃并出现错误undefined is not a function(有关错误和代码片段中回溯的更多详细信息):

注意:以下所有模型都扩展了 BasicModel

// /connection/connection.js

import mysql from 'mysql'
import env from '../env.js'

export default  mysql.createPool({
  port            : env.DB_PORT,
  connectionLimit : env.DB_CONNECTION_LIMIT,
  user            : env.DB_USER,
  password        : env.DB_PASSWORD,
  database        : env.DB_NAME
})
// /routes/v1/orders.js

import { Router } from 'express'
import OrdersController from '../../controllers/OrdersController.js'

const router = Router()
const controller = new OrdersController

// I have a router.js that builds my routes based on my file structure
// so the following GET is equivalent to get(`/v1/orders/`)
router.get('/', controller.all)

export default router
// /controllers/ControllerCommons.js

export default class ControllerCommons {
    all = (req, res) => {
        this.model.all(data => {
            res.json(data)
        })
    }
    
    byId = (req, res) => {
        const id =  parseInt(req.params.brands_id)
        this.model.byId(id, data => res.json({data}))
    }
}
// /controllers/OrdersController.js

import OrdersModel from '../models/OrdersModel.js'
import ControllerCommons from './ControllerCommons.js'

export default class OrdersController extends ControllerCommons{
    model = new OrdersModel
}
// /models/BasicModel.js

import conn from '../connection/connection.js'

export default class BasicModel {
    all(callback = _ => null) {
        const sql = 'SELECT * FROM ??'

        conn.query(sql, [this.table], function(err, result) {
            if (err) return callback(err)
            callback(result)
        })
    }

    byId(id, callback = _ => null) {
        const sql = 'SELECT * FROM ?? WHERE id=?'

        conn.query(sql, [this.table, id], function(err, result) {
            if (err) return callback(err)
            callback(result)
        })
    }
// /models/OrdersModel.js

export default class OrdersModel extends BasicModel {
    table = 'vr_vendors_orders'

    all(callback = _ => null) {
        super.all((data) => {
            data.forEach((order, index) => { // data has 100+ records
                const statusId = order.status_id
                const vendorId = order.vendors_id
                const currencyId = order.currency_id

                this.vendor(vendorId, (vendorResponse) => {
                    // Response is 1 row, 12 fields big (vendorResponse.length === 12)
                    order['vendor'] = vendorResponse
                    delete order.vendors_id
                })

                this.status(statusId, (statusResponse) => {
                    // Response is 1 row, 3 fields big (statusResponse.length === 3)
                    order['status'] = statusResponse
                    delete order.status_id
                })

                this.currency(currencyId, (currencyResponse) => {
                    // Response is 1 row, 3 fields big (currencyResponse.length === 3)
                    order['currency'] = currencyResponse
                    delete order.currency_id
                })

                if (index === data.length - 1) {
                    callback(data)
                }
            })
        })
    }

    vendor = (vendorId, callback = _ => null) => {
        const vendorsModel = new VendorsModel

        vendorsModel.byId(vendorId, ([vendor]) => {
            callback(vendor)
        })
    }

    status = (statusId, callback = _ => null) => {
        const statusesModel = new StatusesModel 

        statusesModel.byId(statusId, ([status]) => {
            callback(status)
        })
    }

    currency = (currencyId, callback = _ => null) => {
        const currencyModel = new CurrencyModel

        currencyModel.byId(currencyId, ([currency]) => { //<----- undefined is not a function Ln:[whatever line this is], Col:40
            callback(currency)
        })
    }
}

问题

  1. 知道为什么会发生错误吗?(注意:所有数据项都有有效的ID)
  2. 任何想法如何改进其构建方式以防止这种情况再次发生?我讨厌我像 eHonda 100 Hand Slap 一样循环访问数据库中的 100 多个项目(我相信TRANSACTION或者LEFT JOIN会更推荐)有什么想法吗?
  3. join()关于如何在 my上构建方法的想法ControllerCommons.js
  4. 对使用Promisify,TRANSACTION和/或LEFT JOIN(带有nestTables选项)的想法?你觉得它会解决问题吗?
  5. 小花絮:更改我在方法中访问数组项的currency方式(是的,仅当我将更改应用于currency方法时才有效)可防止 API 崩溃,但有时它工作正常,有时order['status']为空,有时它根本没有创建:
//        currencyModel.byId(currencyId, ([currency]) => { //<----- undefined is not a function Ln:[whatever line this is], Col:40
//            callback(currency)
//        })

        currencyModel.byId(currencyId, (result) => { // not destructing the array, prevents the crash... but why? Performance? And why just for this method?
            const currency = result[0]
            callback(currency)
        })

想法?

标签: mysqlnode.jsexpressnode-mysql

解决方案


推荐阅读