如何在 Node.js 中使用带有承诺的 MongoDB?

我一直试图发现如何在 Node.js 中使用 MongoDB,在文档中,建议的方法似乎是使用回调。现在,我知道这只是个人喜好的问题,但我真的更喜欢使用承诺。

问题是我没有找到如何在 MongoDB 中使用它们:

var MongoClient = require('mongodb').MongoClient;


var url = 'mongodb://localhost:27017/example';


MongoClient.connect(url).then(function (err, db) {
console.log(db);
});

结果是 undefined。在这种情况下,这似乎不是这样做的方式。

有没有什么方法可以在 Node 中使用 mongodb 来代替回调?

98408 次浏览

You can either use an alternative package, such as mongodb-promise or promisify the mongodb package API manually by building your own promises around it or via a promise utility package like bluebird.promisify

It doesn't look like the connect method has a promise interface defined

http://mongodb.github.io/node-mongodb-native/2.1/tutorials/connect/

you could always implement it yourself in the Mongodb connector library, but that's probably more involved than you are looking for.

If you really need to work with promises, you can always use the ES6 promise polyfill:

https://github.com/stefanpenner/es6-promise

and wrap your connection code with that. Something like

var MongoClient = require('mongodb').MongoClient;
var Promise = require('es6-promise').Promise;


var url = 'mongodb://localhost:27017/example';


var promise = new Promise(function(resolve, reject){
MongoClient.connect(url, function (err, db) {
if(err) reject(err);
resolve(db);
});
});


promise.then(<resolution code>);

Your approach is almost correct, just a tiny mistake in your argument

var MongoClient = require('mongodb').MongoClient
var url = 'mongodb://localhost:27017/example'
MongoClient.connect(url)
.then(function (db) { // <- db as first argument
console.log(db)
})
.catch(function (err) {})

WARNING Edit:

As John Culviner noted, this answer is deprecated. Use the driver, it comes with promises OOTB.


If you choose to use bluebird as a promise library, you can use bluebirds promisifyAll() function on MongoClient:

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


var url = 'mongodb://localhost:27017/example';


MongoClient.connectAsync(url).then(function (db) {
console.log(db);
}).catch(function(err){
//handle error
console.log(err);
});

You need to create a promise that connects to Mongo.

Then, define your function that uses this promise: myPromise.then(...).

For example:

function getFromMongo(cb) {
connectingDb.then(function(db) {


db.collection(coll).find().toArray(function (err,result){
cb(result);
});


});
}

here is the full code:

http://jsfiddle.net/t5hdjejg/

Since none of the answers above mention how to do this without bluebird or q or any other fancy library, let me add my 2 cents on this.

Here's how you do an insert with native ES6 promises

    'use strict';


const
constants = require('../core/constants'),
mongoClient = require('mongodb').MongoClient;






function open(){


// Connection URL. This is where your mongodb server is running.
let url = constants.MONGODB_URI;
return new Promise((resolve, reject)=>{
// Use connect method to connect to the Server
mongoClient.connect(url, (err, db) => {
if (err) {
reject(err);
} else {
resolve(db);
}
});
});
}


function close(db){
//Close connection
if(db){
db.close();
}
}


let db = {
open : open,
close: close
}


module.exports = db;

I defined my open() method as the one returning a promise. To perform an insert, here is my code snippet below

function insert(object){
let database = null;
zenodb.open()
.then((db)=>{
database = db;
return db.collection('users')
})
.then((users)=>{
return users.insert(object)
})
.then((result)=>{
console.log(result);
database.close();
})
.catch((err)=>{
console.error(err)
})
}






insert({name: 'Gary Oblanka', age: 22});

Hope that helps. If you have any suggestions to make this better, do let me know as I am willing to improve myself :)

This is a General answer for How to use MongoDB with promises in Node.js?

mongodb will return a promise if the callback parameter is omitted

Before converting to Promise

var MongoClient = require('mongodb').MongoClient,
dbUrl = 'mongodb://db1.example.net:27017';


MongoClient.connect(dbUrl,function (err, db) {
if (err) throw err
else{
db.collection("users").findOne({},function(err, data) {
console.log(data)
});
}
})

After converting to Promise

//converted
MongoClient.connect(dbUrl).then(function (db) {
//converted
db.collection("users").findOne({}).then(function(data) {
console.log(data)
}).catch(function (err) {//failure callback
console.log(err)
});
}).catch(function (err) {})

Incase you need to handle multiple request

MongoClient.connect(dbUrl).then(function (db) {


/*---------------------------------------------------------------*/


var allDbRequest = [];
allDbRequest.push(db.collection("users").findOne({}));
allDbRequest.push(db.collection("location").findOne({}));
Promise.all(allDbRequest).then(function (results) {
console.log(results);//result will be array which contains each promise response
}).catch(function (err) {
console.log(err)//failure callback(if any one request got rejected)
});


/*---------------------------------------------------------------*/


}).catch(function (err) {})

Working solution with MongoDB version > 3.0

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";




open = (url) => {
return new Promise((resolve,reject) => {
MongoClient.connect(url, (err,client) => { //Use "client" insted of "db" in the new MongoDB version
if (err) {
reject(err)
} else {
resolve({
client
});
};
});
});
};


create = (client) => {
return new Promise((resolve,reject) => {
db = client.db("myFirstCollection"); //Get the "db" variable from "client"
db.collection("myFirstCollection").insertOne({
name: 'firstObjectName',
location: 'London'
}, (err,result)=> {
if(err){reject(err)}
else {
resolve({
id: result.ops[0]._id, //Add more variables if you want
client
});
}


});
});
};


close = (client) => {
return new Promise((resolve,reject) => {
resolve(client.close());
})


};


open(url)
.then((c) => {
clientvar = c.client;
return create(clientvar)
}).then((i) => {
idvar= i.id;
console.log('New Object ID:',idvar) // Print the ID of the newly created object
cvar = i.client
return close(cvar)
}).catch((err) => {
console.log(err)
})

You can also do async/await

async function main(){
let client, db;
try{
client = await MongoClient.connect(mongoUrl, {useNewUrlParser: true});
db = client.db(dbName);
let dCollection = db.collection('collectionName');
let result = await dCollection.find();
// let result = await dCollection.countDocuments();
// your other codes ....
return result.toArray();
}
catch(err){ console.error(err); } // catch any mongo error here
finally{ client.close(); } // make sure to close your connection after
}

I know I am a bit late to the party but I'd like to share an example using ES6

const config = require('config');
const MongoClient = require('mongodb').MongoClient;


var _connection;
var _db;


const closeConnection = () => {
_connection.close();
}


/**
* Connects to mongodb using config/config.js
* @returns Promise<Db> mongo Db instance
*/
const getDbConnection = async () => {
if (_db) {
return _db;
}
console.log('trying to connect');
const mongoClient = new MongoClient(config.mongodb.url, { useNewUrlParser: true });
_connection = await mongoClient.connect();
_db = _connection.db(config.mongodb.databaseName);
return _db;
}


module.exports = { getDbConnection, closeConnection };

I go a bit into more detail here if you want to take a look:

https://medium.com/swlh/how-to-connect-to-mongodb-using-a-promise-on-node-js-59dd6c4d44a7

Here's a one liner to open connection

export const openConnection = async ()  =>
await MongoClient.connect('mongodb://localhost:27017/staticback')

and call it like this

const login = async () =>
const client = await openConnection()

This is based upon @pirateApp's answer.


const open = (dbName, collectionName) => {
const URI = process.env.MONGO_URI;
return new Promise((resolve, reject) => {
let savedConn = null;
MongoClient.connect(URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then((conn) => {
savedConn = conn;
return conn.db(dbName).collection(collectionName);
})
.then((db) => {
resolve({ db, savedConn });
})
.catch((err) => reject(err));
});
};


async function main(){
let client, db;
try{
client = await MongoClient.connect(mongoUrl, {useNewUrlParser: true});
db = client.db(dbName);
let dCollection = db.collection('collectionName');
let result = await dCollection.find();
// let result = await dCollection.countDocuments();
// your other codes ....
return result.toArray();
}
catch(err){ console.error(err); } // catch any mongo error here
finally{ client.close(); } // make sure to close your connection after
}