0

This is a rewrite / simplification of an earlier question, even more simplified but hopefully without confusing things this time. Behold this code:

const mysql = require('mysql-await');

const dbPool = mysql.createPool({
  connectionLimit: 10,
  host: 'localhost',
  port: 8889,
  user: 'admin',
  password: 'admin',
  database: 'cslabelsportal',
  socketPath: '/Applications/MAMP/tmp/mysql/mysql.sock',
});

async function getUserByID(id) {
  if (id) {
    try {
      const rows = await dbPool.awaitQuery(`SELECT * FROM users WHERE id = '${id}'`);
      [user = null] = rows;
      return user;
    } catch (error) {
      return null;
    }
  }
}

async function test() {
  const user = await getUserByID(6);
}
test();

This is run in node.js, but I bypassed almost everything and the problem is still there, so I'm assuming this is to do with either how node.js handles things or ... well, I don't know. What I do know:

awaitQuery is a function that creates a promise and returns it. When all goes well, it resolves the promise, if there is an error it throws, should catch the throw and then rejects the promise. That's how I read this:

  awaitQuery(query, params) {
    return new Promise((resolve, reject) => {
      try {
        if ( typeof params === `undefined` ) {
          this.pool.query(query, (err, result) => {
            if ( err )
              throw err;

            resolve(result);
          });
        } else {
          this.pool.query(query, params, (err, result) => {
            if ( err )
              throw err;

            resolve(result);
          });
        }
      } catch ( err ) {
        reject(err);
      }
    });
  }

The function getUserByID uses await, which is supposed to wait until that promise is settled, then "If the Promise is rejected, the await expression throws the rejected value". So if things go wrong, there should be an exception created in getUserByID. That exception should be catchable in the try... catch block in that function.

Except that the result is this:

...code/node_modules/mysql-await/index.js:505
              throw err;
              ^

Error: connect ENOENT /Applications/MAMP/tmp/mysql/mysql.sock
    at PipeConnectWrap.afterConnect [as oncomplete] (net.js:1137:16)
    --------------------
    at ...code/node_modules/mysql-await/index.js:503:21
    at new Promise (<anonymous>)
    at PoolAwait.awaitQuery (...code/node_modules/mysql-await/index.js:500:12)
    at getUserByID (...code/test/server.js:16:33)
    at test (...code/test/server.js:26:22) {
  errno: 'ENOENT',
  code: 'ENOENT',
  syscall: 'connect',
  address: '/Applications/MAMP/tmp/mysql/mysql.sock',
  fatal: true
}

The fact that the error is caused in the first place is entirely correct, mysql doesn't like it if you shut down the database. What I don't understand is why I still see an exception and what I need to do to do away with it.

David van Driessche
  • 6,602
  • 2
  • 28
  • 41
  • So what's you're saying is the app completely dies, and had you logged the error in the `catch`, where you're currently returning `null` that code path was not reached? – lux Jun 15 '20 at 16:59
  • Your `getUserByID` is entirely fine. The problem is `awaitQuery` which returns a promise that is not rejected, but instead it causes an uncaught exception in an asynchronous callback. – Bergi Jun 15 '20 at 17:00
  • It should be `function awaitQuery(query, params) { return new Promise((resolve, reject) => { this.pool.query(...arguments, (err, result) => { if (err) reject(err); else resolve(result); }); }); }`. Notice the callback does call `reject()`, it does not `throw` anything. – Bergi Jun 15 '20 at 17:05
  • And the exception is not caught _because_ it's in this result callback from pool.query, correct? And I'm assuming that changing the "throw(err)" used in that function to a reject( err) should resolve it then? So basically I'm looking at a bug in this node module? – David van Driessche Jun 15 '20 at 17:09
  • Yes :) Thank you :) That confirms what I just remarked :) – David van Driessche Jun 15 '20 at 17:10

0 Answers0