2

I have some nodejs scripts - i.e. processes which do a job and complete, rather than run continuously.

I use async functions, for example:

const mysql = require('mysql2/promise');
...

async function main() {
    var conn = await mysql.createConnection(config.mysql);
    ...
    var [response, error] = await conn.execute(`
        DELETE something
        FROM some_table
        WHERE field = ?
    `, [value]);
    ...

Is the following code:

main().then(() => process.exit(0)).catch(err => { console.error(err); process.exit(1); });

the best/correct way to start execution of the async code?

(It works, but I want to make sure that I'm not leaving any holes which might cause surprises, such as exceptions being silently swallowed.)

Why does conn.execute() return an error (which I need to manually check) rather than throwing one?

fadedbee
  • 42,671
  • 44
  • 178
  • 308

2 Answers2

2

The use of then together with async..await isn't necessary because it's syntactic sugar for then.

Entry point could be async IIFE (IIAFE):

(async () => {
  try {
    var conn = await mysql.createConnection(config.mysql);
    ...
    var [response] = await conn.execute(`
        SELECT something
        FROM some_table
        WHERE field = ?
    `, [value]);
    ...
    process.exit(0);
  } catch (err) {
    console.error(err);
    process.exit(1);
  }
})();

There also may be no need for process.exit(0) if the connection was closed.

Why does conn.execute() return an error (which I need to manually check) rather than throwing one?

It doesn't, and isn't conventional for promise-enabled functions to return an error in a result.

Callback-based execute uses error-first callback for errors. Promise-based execute can't throw an error because it returns a promise which is rejected in case of error.

As the documentation shows, the second element is fields and not error:

const [rows, fields] = await conn.execute('select ?+? as sum', [2, 2]);

It may return rejected promise which can be caught with try..catch inside async function in case of error.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • I had a cut/paste error, the query was mistakenly a SELECT. It is now, correctly, a DELETE, which does not return `[rows, fields]`. – fadedbee Apr 05 '19 at 09:12
  • I'm unable to currently test what execute returns in case of DELETE but I'm positive it should reject an error, not resolve with it, so it can be caught with try..catch inside async. Why did you decide that it returns an error, *Why does conn.execute() return an error*? – Estus Flask Apr 05 '19 at 09:17
  • I've just done some testing, and bad SQL causes an Error to be thrown, not returned. With good SQL, the return value is the two-element array `[ResultSetHeader, undefined]`, which implies there could be something in the second position. I will post another comment... – fadedbee Apr 05 '19 at 09:57
  • Thanks for your help, I've accepted your answer. I can't find where I read that DELETEs and UPDATEs returned [ResultSetHeader, Error] - I may have just assumed it based on the callbacks from the non-async functions. Still confused as to what might appear in the second position of the returned array. – fadedbee Apr 05 '19 at 10:12
2

The async function declaration defines an asynchronous function, which returns an AsyncFunction object. An asynchronous function is a function which operates asynchronously via the event loop, using an implicit Promise to return its result. But the syntax and structure of your code using async functions is much more like using standard synchronous functions.

You can also define async functions using an async function expression.

async function f() {

  try {
    let response = await fetch('http://no-such-url');
  } catch(err) {
    alert(err); // TypeError: failed to fetch
  }
}

f();

you can also immediately call an asynce function using the syntax below

(async () => {

})();
Rubin bhandari
  • 1,873
  • 15
  • 20
  • 1
    This gives me `SyntaxError: await is only valid in async function`. – fadedbee Apr 05 '19 at 09:16
  • Your first example still looks bad. Are you using nodejs, or a browser? Nodejs doesn't have `alert`. If I replace `alert` and `fetch` with functions which exist, I just get the *promise* **returned**, but **not executed**. – fadedbee Apr 05 '19 at 09:56
  • Its about how to call async . Nothing node specific – Rubin bhandari Apr 05 '19 at 10:12
  • you get the resolved value or reject value. Please look into promise more – Rubin bhandari Apr 05 '19 at 10:12
  • Thanks for your help, but sorry, I don't see that in nodejs v10.15.3. Are you using nodejs or a browser? If you're using nodejs, where are `fetch` and `alert` coming from. – fadedbee Apr 05 '19 at 10:17
  • `f()` returns `Promise { undefined, domain: Domain { domain: null, _events: [Object: null prototype] { removeListener: [Function: updateExceptionCapture], newListener: [Function: updateExceptionCapture], error: [Function: debugDomainError] }, _eventsCount: 3, _maxListeners: undefined, members: [] } }` – fadedbee Apr 05 '19 at 10:20
  • Thats a pseudo code. Replace the insides of the function with your algorithm – Rubin bhandari Apr 05 '19 at 10:20
  • you can use . f().then(res=>{ // handle res }); – Rubin bhandari Apr 05 '19 at 10:20
  • with `main().then(() => process.exit(0)).catch(err => { console.error(err); process.exit(1); });` – fadedbee Apr 05 '19 at 10:23