How to wait for Promise in a non-async function? (node-mssql)

167 views Asked by At

I need to migrate to a MS SQL database and I'm using the node-mssql library.

Problem: the mssql library returns Promises and they don't block the execution of my code.

But my code expects the code to block and I cannot effort refactoring the whole project so I'm looking for a solution to wait for a Promise until it's done and to return its result.

All answers I found do not solve the problem.

When my code queries the database then it must return a result, not a Promise object that is resolved somewhen later. My code needs to block and wait for the Promise to finish (succeed or fail) and continue with its result.

I see that many others do have the same requirement. Why is it so hard to implement an await-like statement in a non-async function? These fancy Promise bullsh*t callbacks are driving you crazy.

An acceptable alternative is to switch to another MS SQL library that acts "like normal".

Here's an example:

// Emulate the node-mssql connect method
// Similar to: const sql = require('mssql')
const sql = {
  connect: (config) => new Promise(resolve => {
    setTimeout(() => resolve({query: (sql) => sql}), 2000)
  })
}

// Existing project structure
class Foo {
  db; // database connection
  
  constructor() {
    this.db_connect();
  }
  
  db_connect() {
    this.db = sql.connect(); // Promise, not connection object
    // must not return until done!
  }
  
  db_query(sql) {
    return this.db.query(sql); // Promise, not result object
    // must not return until done!
  }
}

const foo = new Foo();
console.log(foo.db_query(`SELECT * FROM bar WHERE spam='eggs'`));

// Uncaught TypeError: this.db.query is not a function
1

There are 1 answers

1
Wil Moore III On BEST ANSWER

The constructor cannot be async; however, the other methods can. We'll make those async and we'll instantiate the object and invoke it's methods from within an async main function:

const sql = {
  connect: (config) => new Promise(resolve => {
    setTimeout(() => resolve({query: (sql) => sql}), 2000)
  })
}

// Existing project structure
class Foo {
  db;

  constructor() {
    this.db = null;
  }

  async db_connect() {
    this.db = await sql.connect();
  }

  async db_query(sql) {
    return await this.db.query(sql);
  }
}

const main = async () => {
  const foo = new Foo();
  await foo.db_connect()
  const out = await foo.db_query(`SELECT * FROM bar WHERE spam='eggs'`)
  console.log(out);
};

main();