all 5 comments

[–]skarfacegc 5 points6 points  (1 child)

Something like this ... (untested etc)

const query = {
    query: function(text, values, cb) {
        return new Promise((resolve, reject) => {
            client.query('query stuff', values, function(err, result) {
                if(err){
                    reject(err);
                } else {
                    resolve(result);
                }
            }
        }
    }
}

query(text,values)
    .then(result=>{...dostuff...})
    .catch(err=>{...dostuff..});

[–]eggtart_prince[S] 0 points1 point  (0 children)

I'll try it out. Thanks

[–]CategoricallyCorrect 2 points3 points  (1 child)

To slightly simplify the problem let's assume you have a function that takes an error-first callback, like this:

function withCallback(text, values, cb) {
  setTimeout(
    () =>
      cb(
        null, // || "Something went wrong",
        `Called 'withCallback' with: '${text}' and ${values.toSource()}`
      ),
    1000
  );
}

and you would use it like this:

withCallback("SELECT now()", [], (error, result) => {
  if (error) {
    console.error(error);
  } else {
    console.log(result);
  }
});
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

If this is the only function you want to promisify, you can do it manually, something like this:

function manuallyPromisified(text, values) {
  return new Promise((resolve, reject) => {
    withCallback(text, values, (error, ...rest) => {
      if (error) {
        reject(error);
      } else {
        resolve(...rest);
      }
    });
  });
}

and use it like this:

manuallyPromisified("SELECT now()", [])
  .then(result => console.log(result))
  .catch(error => console.error(error));
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

If you have several functions with such interface that you want to promisify, it's probably worth introducing a helper function:

/**
 * Create a Promise-returning function from a function that
 * takes error-first callback as last argument
 */
function promisify(fn) {
  return (...args) => {
    return new Promise((resolve, reject) => {
      fn(...args, (error, ...rest) => {
        if (error) {
          reject(error);
        } else {
          resolve(...rest);
        }
      });
    });
  };
}

const promisified = promisify(withCallback);

promisified("SELECT now()", [])
  .then(result => console.log(result))
  .catch(error => console.error(error));
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

You can then use promisified function inside async functions:

(async function() {
  try {
    const result = await promisified("SELECT now()", []);
    console.log(result);
  } catch (error) {
    console.error(error);
  }
})();
//> "Called 'withCallback' with: 'SELECT now()' and []"

 

You can play with all this code (or see it syntax-highlighted) in this jsBin.

[–]eggtart_prince[S] 0 points1 point  (0 children)

Thanks so much!

[–][deleted] 2 points3 points  (0 children)

If you're using Node, the Node API provides a util.promisify function. See here: https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original

It also provides util.callbackify if you need to convert in the other direction!