1

I am developing an application based on nodejs and electron, that has to retrieve data from an nedb-database. I have not fully understood the concept of Promises, or I think I have understood it far enough to use it, but it always ends up in a mess of a dozen nested callbacks because of the asynchronous nature of promises.

I am aware of threads like this one and the solutions brought up there. Using callbacks or the .then().method of Promises might be fine if that code path is a "dead end" (e.g. errorhandling), but for many sequential lines, it will end up in endlessly nested code.

I am also aware one should not use return await ...(), but I tried some ways to make an asynchronous method synchronous. The following code brought up some questions:

function getFromDatabase() {
  return new Promise((resolve, reject) => {
    //do something with asynchronous database api
    resolve('database element');
  })
}

async function getSynchronous() {
  var dbElement = await getFromDatabase();
  console.log("before returning: " + dbElement)
  return dbElement;
}

console.log("returned: " + getSynchronous());

The code will return:

returned: [object Promise]
before returning: database element
  1. Why is the same object (dbElement) containing the string when logging it inside the function ('before returning: ...') and containing the promise when handed back through the return of the function

  2. Why is the returned object logged to console before the one inside the function is?

Christian H
  • 75
  • 1
  • 5

1 Answers1

2

Why is the same object (dbElement) containing the string when logging it inside the function ('before returning: ...') and containing the promise when handed back through the return of the function

Every async function returns a Promise for its return value. So when you return a regular value from, an async function - you get a promise for that value.

It is perfectly fine (until we have top level await stable) to wrap your "main" code in an IIFE (immediately invoked function expression) and use await there though:

(async () => { // can use await here

  console.log("returned: " + await getSynchronous());
})();

Why is the returned object logged to console before the one inside the function is?

A promise is value + time, the JavaScript execution model is that synchronous code always runs start-to-finish and you can only "register" things to run by the platform at a later time. So in this case getSynchronous returns synchronously but the await happens after all synchronous code is done.

While there is nothing asynchronous in this code - whenever you await something other synchronous code gets a chance to run first so that if you change the implementation of what you are awaiting to be truly asynchronous or something asynchronous you won't get a nasty race condition in your execution order. This is also true for the way Promise then callbacks execute generally.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • 1
    Ah, that was my misunderstanding! I always thought that the returned promise is that one from inside the function, I didn't expect the function to return a Promise itself! So if I only use async functions, I can always use awaits throughout my whole software whereever needed and that should do the job (except from workarounds for e.g. class constructors)! Thanks! – Christian H Apr 26 '19 at 20:27