0

I'm running NodeJS with pg-promise for accessing my PostgreSQL.

This is my test, which fails with undefined:

function a() {
  pgPromise.one('SELECT 1')
  .then(row => {
     return row;
  })
  .catch(error => {
    console.log(error);
  });
}

console.log(a());

I asume it fails with undefined because it's running asyncronized.

I've tried to optimize with:

async function a() {
  var output = null;
  await pgPromise.one('SELECT 1')
  .then(row => {
     output = row;
  })
  .catch(error => {
    console.log(error);
  });

  return output;
}

console.log(a());

But that simply gives me:

[2018-09-13 08:37:09.521] [LOG]   Promise { <pending> }
Alfred Balle
  • 1,135
  • 4
  • 16
  • 32
  • You call `console.log(a())` with a function that does not return anything. What did you expect? Of course it will print `undefined`. – vitaly-t Sep 13 '18 at 13:26

2 Answers2

2

You must await for the result, so that you don't get the promise but its result once it's solved:

console.log(await a());

But your code is way too complicated. Your a function makes no real sense.

Change

async function a() {
  var output = null;
  await pgPromise.one('SELECT 1')
  .then(row => {
     output = row;
  })
  .catch(error => {
    console.log(error);
  });

  return output;
}

to

async function a() {
  try {
      return await pgPromise.one('SELECT 1')
  } catch(error) {
      console.log(error);
  }
}

If you're getting a syntax error on the await, it probably means you're not in an async function. A typical case in node is when you're at the root. The simplest solution is to wrap it in an async function:

;(async function(){
    console.log(await a());
})();
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • 1
    I'm getting `console.log(await a()); ^^^^^ SyntaxError: missing ) after argument list` – Alfred Balle Sep 13 '18 at 08:52
  • Seems to work, but wow, seems like quite a hack to wrap a pg-promise inside a global function. – Alfred Balle Sep 13 '18 at 08:58
  • async function a() { try { return await pgPromise.one('SELECT 1') } catch error) { console.log(error); } } – John Sep 13 '18 at 08:59
  • 1
    @AlfredBalle you only need that at the root. For the rest everything is supposed to be either async or not and you know it. For a REPL application I always launch node with a modifier: `node --experimental-repl-await myapp.js` – Denys Séguret Sep 13 '18 at 08:59
  • @AlfredBalle It's better for you to first understand how asynchronous code work before using async/await. Unless you are very comfortable with wrapping your entire code inside a SINGLE global function. (note: you may find doing multiple global function wrapper to also not work as you expect. It MUST be a single global function wrapper) – slebetman Sep 13 '18 at 09:00
  • It's simply because I need to run the function `a` many places in my code, which I would like to write it only once. – Alfred Balle Sep 13 '18 at 09:05
  • if you need it at many places, it's always in asynchronous contexts, so in functions which are already async (or you return it as a promise) – Denys Séguret Sep 13 '18 at 09:11
1

async functions return a Promise, so you need to await it or use .then() in order to get the result.

Remember that await can only be used inside an async function so you need to change the structure of your code.

I recommend you check the documentation and also more information asynchronous programming in Javascript.

Keeping your first code like that, it could be fixed like this (still is a bit weird in my opinion):

function a() {
  return pgPromise.one('SELECT 1')
  .then(row => {
     return row;
  })
  .catch(error => {
    console.log(error);
  });
}

a().then(console.log);

If you want to go with async/await, this example could be good for learning purposes:

async function a() {
  const row = await pgPromise.one('SELECT 1');
  return row;
}

a().then(console.log).catch(console.error);

In this case the error handling is being done outside the function, in the caller side (it could be done inside through try/catch, it depends on the use case).

Antonio Val
  • 3,200
  • 1
  • 14
  • 27