question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Promise wrapper on createConnection is problematic in top-level code

See original GitHub issue

The non-promise version of createConnection is not asynchronous. Unlike the database calls, no callback is required here.

var connection = mysql.createConnection({host:'localhost', user: 'root', database: 'test'});

However, the promise wrapper version comes back as a promise.

let connection = await mysql.createConnection({host:'localhost', user: 'root', database: 'test'});

This wouldn’t be a problem, except that Node/V8 don’t currently allow await outside of an async function, including at the top level of an app. This means that the example code doesn’t work when you drop it into a simple Node app. The easy solution that I’ve come up for this, is to wrap createConnection in an IIFE.

let connection

(async function() {
  try {
    connection = await mysql.createConnection(dbconfig)
  } catch(err){
    console.error(err)
  }
})()

This seems unnecessarily complex, since this isn’t a method that needs to be async. I would propose that createConnection remains a synchronous function, the same way it is in the non-promise version. I’m also having difficulty finding an easy way to stick my DB stuff into a module with this pattern.

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:6
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
dougwilsoncommented, Mar 2, 2018

Yea, in fact was just pulling out the AWS certs to share right now :waves:

1reaction
sidorarescommented, Nov 13, 2016

hi @jdhiro

I see your point, I wish 7+ node had repl and top level module wrapper async functions

Here are my thoughts: the only correct way of using connection, even in simple script is like this:

   const conn = mysql.createConnection(opts);
   conn.on('error', (err) => { /* 
      handle non-query errors: connection time, network etc
      connection time errors usually can be handled without 
      dedicated conn.on('error') handler because usually there 
      is a command in the queue and fatal errors are reported 
      down to all commands. However, when there is no 
      command in the queue, or command with no callback
      and there is connection error, error must be handled by
      conn error handler, otherwise it'll be re-thrown and 
      crash process
     */ })
    conn.query('do some sql', (err, res) => {
      if (err) {
         return err;
      }
    })

async .createConnection() helps a little with this, in a way that if there is connection error and no command error can be caught. Unfortunately it’s still possible for ‘error’ connection event to crash process so you must attach listener. My advise is to always use pool, even in scripts - pool handles this error logic automatically.

I’ll think about changing .createConnection() to be sync. Maybe it’s possible to make this backwards compatible

as a work around - if you prefer async wrappers but want to have .createConnection() in top lewel of script without extra wrapping - just don’t use await:

const myAsyncFunc = async (conn, x) =>  {
   const [rows, fields] = conn.query('select 1+?', x)
   console.log(rows);
}

const mysql = require('mysql2/promise');
mysql.createConnection({}).then( (conn) => {
   myAsyncFunc(conn, 1);
   myAsyncFunc(conn, 2);
}).catch((e) => {
  console.log('error!!!', e);
})
Read more comments on GitHub >

github_iconTop Results From Across the Web

NodeJS and closing your MySQL connections — a study
So let's apply the promise wrapper, and then use the pool to do a query, like this: ... In other words, just as...
Read more >
Need to wait for promise result from top level code
You can await the Promise returned by getOrderData() . However, in order to use await you need to wrap your call to getOrderData...
Read more >
Node.js v19.3.0 Documentation
In rare situations, the current store is lost in one of the asynchronous operations. If your code is callback-based, it is enough to...
Read more >
How to write a declarative JavaScript promise wrapper
Learn how to write declarative asynchronous function calls in JavaScript for code that is more readable and easier to maintain.
Read more >
Best Practices for ES6 Promises - DEV Community ‍ ‍
For most cases, wrapping old callback-based APIs with the Promise ... current call stack finishes executing the remaining top-level code.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found