Mongodb节点驱动程序2.0。*与Bluebird 2.9。* promisification

时间:2015-03-18 09:53:04

标签: javascript node.js mongodb promise bluebird

因此,围绕此主题还有一些其他问题,例如: How can I promisify the MongoDB native Javascript driver using bluebird?

然而,它似乎没有解决最新版本的驱动程序,这似乎在尝试promisify时有问题。目前,我可以通过以下方式让MongoClient工作:

Promise.promisifyAll(mongodb.MongoClient); // Using .Prototype here fails to promisify

然而,无论我尝试什么收集似乎都没有使用*async调用,它可能会调用它们,但它们永远不会得到解决或拒绝,因此它们只是悬而未决。

历史上在以前的版本中你只需要Promise.promisifyAll(mongodb)并且你已经完成了,但我不确定如何在新驱动程序中正确处理它。

以下是使用mongo direct promisification connectAsync创建的集合的示例输出,然后从返回的db中获取集合。一旦我尝试对集合做任何事情,它就会挂起并且承诺不会从它返回:

{ s: { pkFactory: { [Function: ObjectID] index: 14727641, createPk: [Function: createPk], createFromTime: [Function: createFromTime], createFromHexString: [Function: createFromHexString], isValid: [Function: isValid], ObjectID: [Circular], ObjectId: [Circular], createPkAsync: [Object], createFromTimeAsync: [Object], createFromHexStringAsync: [Object], isValidAsync: [Object], bindAsync: [Object], toStringAsync: [Object], callAsync: [Object], applyAsync: [Object], lazyAsync: [Object], throttleAsync: [Object], debounceAsync: [Object], delayAsync: [Object], everyAsync: [Object], cancelAsync: [Object], afterAsync: [Object], onceAsync: [Object], fillAsync: [Object] }, db: { domain: [Object], _events: {}, _maxListeners: undefined, s: [Object], serverConfig: [Getter], bufferMaxEntries: [Getter], databaseName: [Getter], options: [Getter], native_parser: [Getter], slaveOk: [Getter], writeConcern: [Getter] }, topology: { domain: [Object], _events: [Object], _maxListeners: undefined, connectTimeoutMS: 500, s: [Object], bson: [Getter], isMasterDoc: [Getter], poolSize: [Getter], autoReconnect: [Getter], host: [Getter], port: [Getter], emitOpen: false, socketTimeoutMS: 0 }, dbName: 'some-db-name', options: {}, namespace: 'some-namespace', readPreference: null, raw: undefined, slaveOk: false, serializeFunctions: undefined, internalHint: null, collectionHint: null, name: 'some-collection-name' } }

4 个答案:

答案 0 :(得分:8)

您可以在要求之后直接进行宣传,如bluebird API docs所示,如下所示:

var Promise = require("bluebird");
var MongoDB = Promise.promisifyAll(require("mongodb"));
var util = require('util');

console.log(util.inspect(MongoDB, { showHidden: true }));

使用bluebird 2.9.14和mongodb驱动程序2.0.22,我得到了这个(简化)结果:

  // ....
  Collection: 
   { [Function]
     [length]: 6,
     [name]: '',
     [arguments]: [Getter/Setter],
     [caller]: [Getter/Setter],
     [prototype]: 
      { [constructor]: [Circular],
        collectionName: [Getter],
        // .... 
        findAsync: [Object],
        insertOneAsync: [Object],
        insertManyAsync: [Object],
        bulkWriteAsync: [Object],
        insertAsync: [Object],
        updateOneAsync: [Object],
        replaceOneAsync: [Object],
        updateManyAsync: [Object],
        updateAsync: [Object],
        deleteOneAsync: [Object],
        removeOneAsync: [Object],
        deleteManyAsync: [Object],
        removeManyAsync: [Object],
        removeAsync: [Object],
        saveAsync: [Object],
        findOneAsync: [Object],
        // ....

并成功查询:

MongoDB.connectAsync('mongodb://localhost:27017/test').then(function(db) {
    return db.collection("orders").findOneAsync({});
}).then(function(orders) {
    console.log(orders);
}).catch(function(err) {
    console.log(err);
});

<强>更新

使用MongoClient对象也可以:

var Promise = require("bluebird");
var MongoDB = Promise.promisifyAll(require("mongodb"));
var MongoClient = Promise.promisifyAll(MongoDB.MongoClient);

MongoClient.connectAsync('mongodb://localhost:27017/test').then(function(db) {
    return db.collection("orders").find({}).toArrayAsync();
}).then(function(orders) {
    console.log(orders)
}).catch(function(err) {
    console.log(err);
});

答案 1 :(得分:7)

默认情况下,如果您未指定回调,mongodb驱动程序将始终返回承诺。但是你可以指示它使用你喜欢的promises库返回promises。

使用node-mongodb-native 2.0驱动程序时,这是一种使用bluebird promises的简单方法:

var Promise = require("bluebird");
var MongoClient = require("mongodb").MongoClient; // Doesn't require promisification

/*...*/
function saveData(data) {
  MongoClient
    .connect(MONGO_CONNECTION_STRING, {
      promiseLibrary: Promise // Here you instruct to use bluebird
    })
    .then(function(db) {
      return db
        .collection('myCollection')
        .insert(data)
        .finally(db.close.bind(db))
    })
    .catch(function(err) {
      console.error("ERROR", err);
    });
}

答案 2 :(得分:1)

简化且更真实的版本:

var Promise = require('bluebird');
var MongoDB = Promise.promisifyAll(require('mongodb'));

MongoDB.MongoClient.connectAsync('mongodb://localhost:27017/test')
  .then(function(db) { // Expose db to query logic
    // need to return a promise to let outer catch handle it
    return db.collection("orders").find({}).toArrayAsync()
      .then(function (orders) {
        console.log(orders);
      })
      // Ensure that db is closed at the end no matter what...
      .finally(db.close.bind(db)); 
      // No need for another catch here, the outer one will handle it 
  })
  .catch(console.log.bind(console));

Promise嵌套是为了将db暴露给其余逻辑而完成的。通过传递或声明“数据”可以在不嵌套的情况下完成相同的操作。全球。尝试了一切,这是最优雅的。

答案 3 :(得分:0)

您可以阅读MongoDB Native Driver的来源:

MongoClient.connect = function(url, options, callback) {
  var args = Array.prototype.slice.call(arguments, 1);
  callback = typeof args[args.length - 1] == 'function' ? args.pop() : null;
  options = args.length ? args.shift() : null;
  options = options || {};

  // Get the promiseLibrary
  var promiseLibrary = options.promiseLibrary;

  // No promise library selected fall back
  if(!promiseLibrary) {
    promiseLibrary = typeof global.Promise == 'function' ?
      global.Promise : require('es6-promise').Promise;
  }

  // Return a promise
  if(typeof callback != 'function') {
    return new promiseLibrary(function(resolve, reject) {
      connect(url, options, function(err, db) {
        if(err) return reject(err);
        resolve(db);
      });
    });
  }

  // Fallback to callback based connect
  connect(url, options, callback);
}

可以设置 promiseLibrary Bluebird