How to reuse a mongo connection with promises

2019-08-05 06:46发布

问题:

How can I change things around in my db connection call so that I can do db.collection():

// Create a Mongo connection
Job.prototype.getDb = function() {
  if (!this.db)
    this.db = Mongo.connectAsync(this.options.connection);
  return this.db;
};

// I want to be able to do this
Job.prototype.test = function() {
  return this.db.collection('abc').findAsync()...
};

// Instead of this
Job.prototype.test = function() {
  return this.getDb().then(function(db) {
    return db.collection('abc').findAsync()...
  });
};

My code always calls getDb so the connection does get created so that is not an issue. ex:

this.getDb().then(test.bind(this));

But I actually string many of these calls around so looking for a cleaner approach.

This works - just wondering if there an overall better approach to dealing with this.

Job.prototype.getDb = function(id) {
  var self = this;
  return new P(function(resolve, reject) {
    if (!self.db) {
      return Mongo.connectAsync(self.options.connection)
      .then(function(c) {
        self.db = c;
        debug('Got new connection');
        resolve(c);
      });
    }
    debug('Got existing connection');
    resolve(self.db);
  });
};

I suppose this is really just a mongo connection issue, perhaps not just promises. All the Mongo examples I see either just make all their calls inside of the connect callback or use some framework like Express and assign it on start.

回答1:

I want to be able to do this

return this.db.collection('abc').findAsync()

No, that's impossible when you don't know whether the database is already connected or not. If you might need to connect at first, and that is asynchronous, then this.db must yield a promise, and you'll need to use then.

Notice that with Bluebird you can shorten that code a bit, and avoid that verbose .then() callback by using the .call() method:

Job.prototype.getDb = function() {
  if (!this.db)
    this.db = Mongo.connectAsync(this.options.connection);
  return this.db;
};
Job.prototype.test = function() {
  return this.getDb().call('collection', 'abc').call('findAsync');
};