Home > Software design >  Why is my argument not defined when invoking a DB call?
Why is my argument not defined when invoking a DB call?

Time:05-10

I am using trying to return a Postgres DB query via a GraphQL resolver. For some reason, result is coming back as not defined when I (on purpose) query a row for an ID that doesn't exist. When I console log it, result always comes back as expected:

result = {
 rows: [],
 ...
}

However, when I run it and make a Query, or when I use node inspect index.js and let it run until the debugger, it doesn't seem to recognize that result is even defined. When I run console.log(result) in Node when it hits the debugger, I get this error:

debug> console.log(result)
REPL2:1
console.log(result)
            ^

Uncaught ReferenceError: result is not defined
    at REPL2:1:13
    at Script.runInContext (node:vm:139:12)
    at Object.runInContext (node:vm:289:6)
    at REPLServer.controlEval (node:internal/debugger/inspect_repl:578:25)
    at bound (node:domain:421:15)
    at REPLServer.runBound [as eval] (node:domain:432:12)
    at REPLServer.onLine (node:repl:898:10)
    at REPLServer.emit (node:events:527:28)
    at REPLServer.emit (node:domain:475:12)
    at [_onLine] [as _onLine] (node:internal/readline/interface:424:12)

and when I run the query from the Playground, I get this error:

/Users/user/Projects/geolocatr_api/db/queries/user.queries.js:21
          id: user.id,
                   ^

TypeError: Cannot read properties of undefined (reading 'id')
    at /Users/user/Projects/geolocatr_api/db/queries/user.queries.js:21:20
    at Query.<anonymous> (/Users/user/Projects/geolocatr_api/node_modules/pg-pool/index.js:417:18)
    at Query.handleReadyForQuery (/Users/user/Projects/geolocatr_api/node_modules/pg/lib/query.js:138:12)
    at Client._handleReadyForQuery (/Users/user/Projects/geolocatr_api/node_modules/pg/lib/client.js:290:19)
    at Connection.emit (node:events:527:28)
    at /Users/user/Projects/geolocatr_api/node_modules/pg/lib/connection.js:114:12
    at Parser.parse (/Users/user/Projects/geolocatr_api/node_modules/pg-protocol/dist/parser.js:40:17)
    at Socket.<anonymous> (/Users/user/Projects/geolocatr_api/node_modules/pg-protocol/dist/index.js:11:42)
    at Socket.emit (node:events:527:28)
    at addChunk (node:internal/streams/readable:324:12)

Node.js v18.0.0
error Command failed with exit code 1.

I'm really not sure why my console logs seem to see that something is there, but Node doesn't. Otherwise, when an ID that exists in the table is passed in, it works as expected.

The code:

// Resolver

  Query: {
    user: ( _, { id } ) => {
      console.log({id}); // Node recognizes this as the correct number
      return getUserById(id);
    },
  },


// DB Query Function

const getUserById = (id) => {
  return new Promise(function(resolve, reject) {
    db.query(
      `
        SELECT id, first_name, email, phone
        FROM users
        WHERE id = $1;
      `,
      [id],
      function(err, result) {
        // debugger; // Result comes back as not defined
        if (!result.rows) { // Will not run this if block
          console.log(result.rows);
          reject("Could not find user.");
        }
        if (err) reject(err);
        const user = rows[0];

        resolve({
           id: user.id,
           firstName: user.first_name,
           email: user.email,
           phone: user.phone,
        });
      }
    );
  });
};

CodePudding user response:

Typically with those (err, result) => { ... } callbacks, you check err first because if it is truthy, there's a good chance that the second argument will not be defined.

You should also return after detecting an error to prevent the rest of your callback from executing.

FYI, node-postgresl supports promises natively so there's no need to explicitly create one. Below I've translated your code to an async function to take advantage of this.

const getUserById = async (id) => {
  const { rows } = await db.query({
    text: "SELECT id, first_name as firstName, email, phone FROM users WHERE id = $1",
    values: [id],
  });

  // `rows` is always an array so check the length
  if (rows.length !== 1) {
    throw new Error(`Could not find user by id [${id}]`);
  }

  return rows[0];
};
  • Related