title: Knex transaction Promises warnings
body: <p>I am having a hard time working with Knex, transactions and Promises and would appreciate the help of the experts of SO :)</p>
  
  <p>From reading similar posts and many many articles on Promises, I understand that I am not too far from the solution, but find that the following code is really overly complicated for such a simple task.</p>
  
  <p>This class simply exposes a function that receives a query that was built previously and needs to run it after first calling a "load_user_settings" function (using PostgreSQL 9.5 as a DB). I actually need the result (or error) of the 2nd query, so simply putting trx.commit in the "then" does not work for me.</p>
  
  <p>The process.nextTick at the end of my function really feels like a huge hack and was added in order to avoid changing my entire application to Promises since that is not doable at the moment. Without that, I often found myself with Promise warnings ("Unhandled rejection Error") and hanging code when an exception was thrown later in my code.</p>
  
  <p>Also, I can see the following warning in my logs from time to time : 
  Warning: a promise was rejected with a non-error: [object Undefined]
  and I guess that that warning is somehow related to this problem...</p>
  
  <p>If a solution using only callbacks could be found, that would also be great, as our entire application is currently using callbacks.</p>
  
  <pre><code>const pg = require('pg');
  const async = require('async');
  
  class MyClass {
  
      constructor(connectionInfo) {
          this.connectionInfo = connectionInfo; // This is an object containing user, password, database, host and port.
  
          this.pgKnex = require('knex')({
              client : 'pg',
              connection : this.connectionInfo,
              pool : {
                  min : 1,
                  max : 25
              }
          });
      }
  
      query(username, sql, params, callback) {
          let response;
          let error;
  
          this.pgKnex.transaction((trx) =&gt; {
              return this.pgKnex.raw(`SELECT load_user_settings(?)`, [username]).transacting(trx)
                  .then(() =&gt; {
                      return this.pgKnex.raw(sql, params).transacting(trx);
                  })
                  .then((result) =&gt; {
                      response = result;
                      return trx.commit();
                  }).catch((err) =&gt; {
                      error = err;
                      console.error(err);
                      return trx.rollback();
                  });
          }).catch((err) =&gt; {
              error = err;
              console.error(err);
          }).then(() =&gt; {
              process.nextTick(() =&gt; {
                  callback(error, response);
              });
          });
      }
  }
  
  module.exports = MyClass;
  </code></pre>
  
  <p>Following the comment made by Bergi, I wrote this version which avoids any hacks and removes all the promise warnings that I had : </p>
  
  <pre><code>query(username, sql, params, callback) {
      this.pgKnex.transaction((trx) =&gt; {
          this.pgKnex.raw(`SELECT set_config('ims.username', ?, false)`, [username]).transacting(trx).asCallback((err, result) =&gt; {
              if(err) {
                  trx.rollback().asCallback(() =&gt; {
                      console.error(err);
                      callback(err);
                  });
                  return;
              }
  
              this.pgKnex.raw(sql, params).transacting(trx).asCallback((err, result) =&gt; {
                  if(err) {
                      trx.rollback().asCallback(() =&gt; {
                          console.error(err);
                          callback(err);
                      });
                      return;
                  }
  
                  trx.commit().asCallback((commitErr) =&gt; {
                      callback(commitErr, result);
                  });
              });
          });
      }).asCallback((err, result) =&gt; {
          // Nothing to do here ... I guess?
      });
  }
  </code></pre>
  
  <p>But I still feel like I this could be improved...</p>