Chris Rutherford
Chris Rutherford

Reputation: 1672

Where is the unhandled promise rejection? How can I avoid it?

Working with Node and mssql to pull queries for five different databases to de-dupe against each other and merge into a more unified schema.

My process follows this algorithm:

create a shared pool by calling this function:

const getPoolConnection = async () => {
  try {
    let pool = await mssql.connect(`mssql://${username}:${password}@${server}/`);
    return pool;
  } catch (err) {
    console.error(err);
  }
};

This function creates the pool and returns it to the calling function. username, password, and server are imported and scoped to this file.

Then we query each database and assign the result to a property on an object. This is accomplished via a forEach loop:

lists.forEach(list => {
  fullData[list] = db.queryDatabase(pool, customers[list].query).catch(err => console.error(err));
})

which calls this function:

const queryDatabase = async (pool, query) => {
  try {
    let result = await pool.request().query(query);
    // console.log(result);
    return result.recordset, pool;
  } catch (err) {
    console.error(err);
  }
};

now in order to keep post-processing from occuring before all database calls return data, I've wrapped the entire set of calls in a Promise.all() call in the main index.js file. This is the calling funciton:

const { customers } = require('./query');
const util = require('./util');
const db = require('./db');

fullData = {};

(async () => {
  let pool = await db.getPoolConnection();
  let lists = Object.keys(customers);
  Promise.all(
    lists.forEach(list => {
      fullData[list] = db.queryDatabase(pool, customers[list].query).catch(err => console.error(err));
    })
  )
    .then(results, pool => {
      console.dir(results);
      db.closePoolConnection(pool);
    })
    .catch(err => console.error(err));
})();

What I don't understand is this error that occurs when attempting to debug the application:

(node:18908) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined warning.js:18 at Function.all () at c:\Users\rutherfordc\Documents\GitHub\migration-plus\index.js:10:11 at at process._tickCallback (internal/process/next_tick.js:188:7) (node:18908) 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) warning.js:18 (node:18908) [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. warning.js:18 (node:18908) UnhandledPromiseRejectionWarning: ReferenceError: results is not defined warning.js:18 at c:\Users\rutherfordc\Documents\GitHub\migration-plus\index.js:15:11 at at process._tickCallback (internal/process/next_tick.js:188:7) (node:18908) 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: 2)

Upvotes: 0

Views: 1045

Answers (2)

Prerak Sola
Prerak Sola

Reputation: 10009

Promise.all() needs an array. So you could do something like this:

fullData = [];

(async () => {
  let pool = await db.getPoolConnection();
  let lists = Object.keys(customers);
  lists.forEach(list => {
    fullData.push(db.queryDatabase(pool, customers[list].query).catch(err => console.error(err));
  }));

  Promise.all(fullData)
    .then((results, pool) => {
      console.dir(results);
      db.closePoolConnection(pool);
    })
    .catch(err => console.error(err));
})();

Update:

Also as J. Pichardo suggested in his answer, in case of multiple parameters, the parameters should be enclosed in parentheses.
Documentation

Upvotes: 1

J. Pichardo
J. Pichardo

Reputation: 3115

The error is non-logical but syntactical, the following lines in the main function

.then(results, pool => {
  console.dir(results);
  db.closePoolConnection(pool);
})

The arguments of the arrow function should be surrounded by parentheses, like:

.then((results, pool) => {
  console.dir(results);
  db.closePoolConnection(pool);
})

ReferenceError: results is not defined

So, the then is looking for a results variable and since it is an async function when it crashes it will be a UnhandledPromiseRejection.

Update:

As the other answer says Promise.all receives either multiple promises or an array of promises, so you could do something like:

var fullData = lists.map(list => db.queryDatabase(pool, customers[list].query).catch(err => console.error(err)));

Promise.all(fullData).then(...)

Upvotes: 1

Related Questions