Promisificando manualmente pg.connect con Bluebird

Quiero pg.connect método pg.connect de node-postgres junto con el método de connection.query interno proporcionado en la callback.

Puedo .promisify este último, pero necesito implementar el primero manualmente (si me falta algo aquí, por favor explique).

La cosa es, ¿no estoy seguro de si este código es correcto o debería mejorarse? El código está funcionando, solo quiero saber si estoy usando Bluebird como se indica.

 // 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; }; 

Deseche todo ese horrible código de callback, luego haga esto en algún lugar de la inicialización de su aplicación:

 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); 

Más adelante, en cualquier lugar, puede usar el módulo pg como si estuviera diseñado para usar promesas para comenzar con:

 // 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(); }); }); 

Por ahora hay varias bibliotecas que hacen esto por ti:

  • pg-promise – Promesas genéricas / A + para PG
  • postgres-bluebird
  • dbh-ph
  • pg-bluebird

Actualización para bluebird 3 :

La pg.connectAsync(...).spread(function(connection, release) { ... }) ya no funcionará, porque la API de bluebird ha cambiado: http://bluebirdjs.com/docs/new- in-bluebird-3.html # promisification-api-changes .

El problema es que promisifyAll en bluebird 3 no maneja múltiples argumentos por defecto. Esto da como resultado que la llamada .spread() informe un TypeError como el siguiente:

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

Para resolver esto, puede habilitar explícitamente múltiples argumentos para connect / connectAsync . Haz lo siguiente después de todas las cosas prometedoras mencionadas anteriormente:

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

Sugiero modificar un poco la solución de Petka Antonov.

 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); 

aquí 'pg[key] envuelta en el bloque try-catch porque pg[key] puede volver a generar un error cuando se intenta acceder a pg['native']