Search code examples
node.jses6-promisegraphql

Graphql postgresql promise executes after the results are returned


I'm trying out graphql. I'm pulling my data from postgresql and everyting seems to work except for one issue where the resolve completes before the query has completed. I though I had my query promise working correctly. Here my class that I created to query the database:

class PgPoolClient {

    constructor(options) {
        this.connection = options.connection;
    }

    query(sql, data = []) {

        return new Promise((resolve, reject) => {
            var pool = new pg.Pool(this.connection);
            pool.connect((err, client, done) => {
                if (err) {
                    reject({
                        code: 505,
                        message: err.message,
                        entrys: []
                    });
                } else {
                    client.query(sql, data, (err, results) => {
                        done();
                        if (err) {
                            reject({
                                code: 404,
                                message: err.message,
                                entrys: []
                            });
                        } else {
                            resolve({
                                code: 200,
                                message: "ok",
                                entrys: results
                            });
                        }
                    });
                }
            });

            pool.on("error", (err, client) => {
                reject({
                    code: 505,
                    message: err.message,
                    entrys: {}
                });
            });

        });
    }
}

Here is my graphql Query:

const Query = new GraphQLObjectType({
    name: 'Query',
    description: 'Root query object',
    fields: () => ({
        accounts: {
            type: new GraphQLList(Account),
            resolve(root, args) {

                const parameters = [];
                pg.query(`SELECT
id, token, user_identifier as userIdentifier, hash_password as hashPassword,
is_enabled as isEnabled, security_type_id as securityTypeID,
is_admin as isAdmin, ad_path as adPath, date_created as dateCreated,
date_modified as dateModified, modified_by as modifiedBy
FROM accounts.account`, parameters)
                .then((result) =>
                {
                    console.log(result.entrys.rows);
                    //return result.entrys.rows;
                    return [
                        {
                        id: '33333',
                        token: '111',
                        userIdentifier: 'test'
                        }
                    ]

                })
                .catch((err) =>
                {
                    console.log(err);
                    return err.message;
                });

                console.log('finished');
        }
    })
});

I commented out my results and just wanted to see about returning static content and it seems that when its within then() the results don't get returned to graphisql (meaning the resolve completed before then() does). with output:

{
  "data": {
   "accounts": null
 }

}

I was able to verify this by putting the static return array below the console.log('finished') and it returns the data properly.

console.log('finished');
return [
    {
    id: '33333',
    token: '111',
    userIdentifier: 'test'
    }
]                   

which shows up in graphiql:

{
  "data": {
    "accounts": [
      {
        "id": "33333",
        "token": "111",
        "userIdentifier": "test"
      }
    ]
  }
}

So it seems that my Promise is not being waited on. Is there something I'm missing in my query function that is causing the resolve not to wait for my results? Any help would be appreciated.

Update 1

It seems if I wrapp the query in a Promise it works:

return new Promise((resolve, reject) => {

pg.query(`SELECT
id, token, user_identifier as userIdentifier, hash_password as hashPassword,
is_enabled as isEnabled, security_type_id as securityTypeID,
is_admin as isAdmin, ad_path as adPath, date_created as dateCreated,
date_modified as dateModified, modified_by as modifiedBy
FROM accounts.account`, parameters)
.then((result) =>
{
    console.log(result.entrys.rows);
    //return result.entrys.rows;
    resolve( [
        {
        id: '33333',
        token: '111',
        userIdentifier: 'test'
        }
    ]);

})
.catch((err) =>
{
    console.log(err);
    reject(err.message);
});

I guess my question is if my query function is already wrapped in a Promise, why do I have to do it again?


Solution

  • Your resolve function needs to return the promise. When you explicitly wrapped it in a promise, it worked because you returned it. It should work without that if you return the result of calling pg.query.

    const Query = new GraphQLObjectType({
    name: 'Query',
    description: 'Root query object',
    fields: () => ({
        accounts: {
            type: new GraphQLList(Account),
            resolve(root, args) {
                const parameters = [];
                return pg.query(`query`, parameters)
                .then((result) =>
                {
                    console.log(result.entrys.rows);
                    //return result.entrys.rows;
                    return [
                        {
                        id: '33333',
                        token: '111',
                        userIdentifier: 'test'
                        }
                    ]
                })
                .catch((err) =>
                {
                    console.log(err);
                    return err.message;
                });
                console.log('finished');
            }
        })
    });