Manually promisifying pg.connect with Bluebird

前提是你 提交于 2019-12-18 02:54:48

问题


I want to promisify node-postgres' pg.connect method along with the inner connection.query method provided in the callback.

I can .promisify the latter, but I need to implement the first one manually (if I'm missing something here, please explain).

The thing is, I'm not sure if this code is correct or should be improved? The code is working, I just want to know if I'm using Bluebird as meant.

// aliases
var asPromise = Promise.promisify;

// save reference to original method
var connect = pg.connect.bind(pg);

// promisify method
pg.connect = function (data) {
  var deferred = Promise.defer();

  connect(data, function promisify(err, connection, release) {
    if (err) return deferred.reject(err);

    // promisify query factory
    connection.query = asPromise(connection.query, connection);

    // resolve promised connection
    deferred.resolve([connection,release]);
  });

  return deferred.promise;
};

回答1:


Throw all that horrible callback code away, then do this somewhere in your application initialization:

var pg = require("pg");
var Promise = require("bluebird");

Object.keys(pg).forEach(function(key) {
    var Class = pg[key];
    if (typeof Class === "function") {
        Promise.promisifyAll(Class.prototype);
        Promise.promisifyAll(Class);
    }
})
Promise.promisifyAll(pg);

Later in anywhere you can use the pg module as if it was designed to use promises to begin with:

// Later
// Don't even need to require bluebird here
var pg = require("pg");
// Note how it's the pg API but with *Async suffix
pg.connectAsync(...).spread(function(connection, release) {
     return connection.queryAsync("...")
         .then(function(result) {
            console.log("rows", result.rows);
         })
         .finally(function() {
            // Creating a superfluous anonymous function cos I am
            // unsure of your JS skill level
            release();
         });
});



回答2:


By now there are a number of libraries which do this for you:

  • pg-promise - generic Promises/A+ for PG
  • postgres-bluebird
  • dbh-ph
  • pg-bluebird



回答3:


Update for bluebird 3:

The pg.connectAsync(...).spread(function(connection, release) { ... }) call will not work anymore, because the API of bluebird has changed: http://bluebirdjs.com/docs/new-in-bluebird-3.html#promisification-api-changes .

The problem is that promisifyAll in bluebird 3 does not handle multiple arguments by default. This results in the .spread() call reporting a TypeError like the following:

TypeError: expecting an array or an iterable object but got [object Null]

To solve this, you can explicitly enable multiple arguments for connect / connectAsync. Do the following after all the promisifying stuff mentioned above:

...
pg.connectAsync = Promise.promisify(pg.connect, { multiArgs: true });



回答4:


I suggest to modify Petka Antonov solution a bit

var Promise = require('bluebird');
var pg = require('pg');
Object.keys(pg).forEach(function (key) {
  var Cls = null;
  try {
    Cls = pg[key];
    if (typeof Cls === 'function') {
      Promise.promisifyAll(Cls.prototype);
      Promise.promisifyAll(Cls);
    }
  } catch (e) {
    console.log(e);
  }
});
Promise.promisifyAll(pg);

here 'pg[key] wrapped up in try-catch block because pg[key] can retrun error when attempt to access pg['native']



来源:https://stackoverflow.com/questions/23881058/manually-promisifying-pg-connect-with-bluebird

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!