0

edit: based on responses I've updated my example and response.

I'm really struggling to understand async and await. The moment I feel like I am understanding it, it then doesn't work how i would expect. I'm sure the below is pretty obvious to most people, but there seems to be a clear concept that i failing to grasp. I've tried reading guides and tutorials but the understanding is still escaping me.

The code I'm working is node js and uses express to receive HTTP requests. When the HTTP request is received, it calls a service, and this service calls a database service which in turn calls the MSSQL node library.

To demonstrate this in a simple way, i created a small sample JS file.

async function getData() {

  var serviceData = await serviceGetData();
  console.log('response ' + serviceData.message);
}

async function serviceGetData() {
  var databaseData = await databaseGetData();
  return databaseData;
}

async function databaseGetData() {
  var libraryData = await libraryGetData();
  return libraryData; // i also tried just libraryData

}

function libraryGetData() {
  return new Promise((reject, resolve) => {
    setTimeout(function() {
      var object = { message: 'Hello World' };
      resolve(object);
    }, 1000);
  });
}
getData();

My thought is, it would traverse through the functions, get to the await, call the library function, wait for the response and then come all the way back up the chain and output to console.

As you probably can tell, this isn't what happens. It does come back up the chain, but instead it outputs:

(node:4688) UnhandledPromiseRejectionWarning: #<Object>
(node:4688) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:4688) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I find this strange, because I thought it would wait at the await, and then traverse back up with the message. I also find it strange that serviceData is a promise? This implies i have to chain the promise all the way up, but I thought the whole point of async / await was not to need to chain any more.

Can someone point me in the right direction please?

Piercy
  • 809
  • 1
  • 11
  • 33
  • 1
    You need to bubble up your async/awaits. Make serviceGetData and getData async and await on the async functions inside of them. I didn't read your whole post- but this is the biggest issue I see glancing at your code example. Once you go async, you need to make all functions that use that async function async as well – chevybow Nov 13 '19 at 17:19
  • Please change the order of your function declaration and most probably your one of the `async (promise )` is rejected (may be database) and as you are not handling the error ,you are getting that trace. – Shubham Dixit Nov 13 '19 at 17:21
  • @chevybow , thanks for this. I still cannot get it working, see the modified version in the original question. Thanks – Piercy Nov 13 '19 at 17:29

1 Answers1

2

There's one important thing to understand about async/await: An async function always returns a Promise. Without exception! The promise will resolve synchronously if the async function returns a constant value, but you still need to treat it as a promise.

This means right here: var databaseData = databaseGetData(); you are setting databaseData to a promise, because databaseGetData() is an async function. You need to await the promise, which means, indeed, serviceGetData() also should be async, which means, yep, getData() also needs to be. This reveals an important principle of async/await: if a function will do any asynchronous action anywhere down its calling chain, that function inevitably will need to handle a promise - there's no way around that, you can't bring asynchronous results up into a synchronous context.

Edit in response to question update: You're also getting an uncaught promise rejection because you've swapped the order of resolve and reject in new Promise((reject, resolve) => { - thus when you call resolve(object) you're actually rejecting that promise with object as the error message.

Klaycon
  • 10,599
  • 18
  • 35
  • thanks for this. I still cannot get it working, see the modified version in the original question. Thanks – Piercy Nov 13 '19 at 17:28