0

I'm building a very rudimentary ORM while I learn Node. I have the constructor currently accept either a name or id parameter but not both. If the name is provided, the class creates the record in the database. If the id is provided, it looks up the record. Here's the complete file.

const mysql = require('mysql2/promise');
const { v4: uuid } = require('uuid');

const pool = require('../helpers/pool.js');
const xor = require('../helpers/xor.js');

class List {
    constructor({ name = null, id = null} = {}) {
        if (!xor(name, id)) {
            throw new TypeError('Lists must have either a name or an id');
        }
        this.table_name = 'lists';
        if (name) {
            this.name = name;
            this.uuid = uuid();
            this.#insert_record();
            return;
        }
        this.id = id;
        this.#retrieve_record();
    }

    async #insert_record() {
        await pool.query(
            `INSERT INTO ${this.table_name} SET ?`,
            {
                name: this.name,
                uuid: this.uuid
            }
        ).then(async (results) => {
            this.id = results[0].insertId;
            return this.#retrieve_record();
        });
    }

    async #retrieve_record() {
        return await pool.execute(
            `SELECT * FROM ${this.table_name} WHERE id = ?`,
            [this.id]
        ).then(([records, fields]) => {
            this.#assign_props(records[0], fields);
            pool.end();
        })
    }

    #assign_props(record, fields) {
        fields.forEach((field) => {
            this[field.name] = record[field.name];
        })
        console.log(this);
    }
}

const list = new List({name: 'my list'});
const db_list = new List({id: 50});

You probably see the problem run this as is. I get intermittent errors. Sometimes everything works fine. Generally I see a console log of the retrieved list first, and then a see a log of the new list. But sometimes the pool gets closed with the retrieval before the insert can happen.

I tried placing the pool within the class, but that just caused other errors.

So, what's the proper way to have an ORM class use a connection pool? Note that I'm building features as I learn, and eventually there'll be a Table class from which all of the entity classes will inherit. But I'm first just trying to get this one class to work properly on its own.

Chuck
  • 4,662
  • 2
  • 33
  • 55
  • FYI, there's no point to `return await pool.execute().then()`. It can just be `return pool.execute().then()`. Also, `#insert_record()` has no return value, but it looks like you're wanting `this.#retrieve_record()` to be the resolved value. – jfriend00 Nov 03 '20 at 20:32
  • @jfriend00 Thanks for the tip about the return value, and the `return` in `return this.#retrieve_record();` was a vestige of then `#insert_record()` was also retrieving the data. – Chuck Nov 03 '20 at 21:07

0 Answers0