1

By using mysql2 with promise, I have the controller.js as below :

exports.company_add = (req, res) => {
    company_model.company_add(admin_email, admin_info).then((result) => { ... })
    .catch((err) => { ... })
}

And the model.js as below :

exports.company_add = (admin_email, admin_info) => {
    return new Promise((resolve, reject) => {
        connectionPool.getConnection((connectionError, connection) => {
        if (connectionError) reject(connectionError);
        return connection.promise().query('SELECT * FROM admin WHERE admin_email = ?', [admin_email])
            .then(([rows, field]) => {
                if (rows.length) reject('Email exist');
                else return connection.promise().query('INSERT INTO companydb.admin SET ?', [admin_info])
            })
            .then((result) => {
                console.log('result')
                if (result[0].affectedRows === 1) resolve(result);
                else reject('INSERT FAIL');
            })
            .catch((err) => {
                reject(err);
            })
            .finally(() => {
                connection.release();
            })
    });
    });
};

I wonder how I escape from the .then() statement when the line if (rows.length) occurred, since there is no need to continue with the next .then() for this case if the email already exist in the database. Do I need to throw it and add a .catch() just before the next .then() executed?

K the Kelvin
  • 82
  • 1
  • 8
  • Hmn, if so, how can I handle the `reject('Email exist')` correctly by using promise? I tried in my application and yes, it does receive the `reject()` value but the code continuously executed until the last `.then()` – K the Kelvin Aug 14 '20 at 08:52
  • Does it means that I only execute one query per promise and decide to proceed or not with the next query according to the result? – K the Kelvin Aug 14 '20 at 08:55
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Aug 14 '20 at 09:58

1 Answers1

1

One cannot really break out of a then chain other than by nesting or throwing an exception. Yes, in this case you probably should throw, but you don't need to .catch it when you avoid the Promise constructor antipattern and just make it a chained promise:

exports.company_add = (admin_email, admin_info) => {
    return connectionPool.getConnection().then(connection => {
        return connection.promise().query('SELECT * FROM admin WHERE admin_email = ?', [admin_email])
        .then(([rows, field]) => {
            if (rows.length)
                throw new Error('Email exist');
            else
                return connection.promise().query('INSERT INTO companydb.admin SET ?', [admin_info])
        })
        .then((result) => {
            console.log('result')
            if (result[0].affectedRows !== 1)
                throw new Error('INSERT FAIL');
            return result;
        })
        .finally(() => {
            connection.release();
        })
    }, err => {
        console.error(err);
        throw new Error('CONNECTION FAIL');
    });
};
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 2
    And consider using a [disposer pattern](https://stackoverflow.com/a/28915678/3478010) .... particularly useful if the codebase has many interactions with the database. – Roamer-1888 Aug 16 '20 at 01:03
  • @Bergi Thanks for your information and I had modified my code along with the promises supported `getConnection()` and the result is shown here : [link](https://ibb.co/kMNLwfp) It works nicely but I do have some doubt about the `.catch()`. Should I put it inside my code? Since I already implemented the `throw new Error()` in it. But if I not using `.catch()`, how do I catch the error when `.getConnection()` failed? Not sure about the correctness of the code structure. – K the Kelvin Aug 16 '20 at 05:48
  • 1
    @KtheKelvin You can [use the second `.then(…, …)` parameter](https://stackoverflow.com/q/24662289/1048572) for that (see edit). Or put the `catch` there and have it distinguish between the `INSERT FAIL` error thrown from inside the chain and other database errors. Or just drop the `catch` and simply let errors propagate. – Bergi Aug 16 '20 at 13:06