Làm thế nào để sử dụng MongoDB với các hứa hẹn trong Node.js?


82

Tôi đã cố gắng khám phá cách sử dụng MongoDB với Node.js và trong tài liệu, có vẻ như cách được đề xuất là sử dụng các lệnh gọi lại. Bây giờ, tôi biết rằng đó chỉ là vấn đề sở thích, nhưng tôi thực sự thích sử dụng những lời hứa hơn.

Vấn đề là tôi không tìm thấy cách sử dụng chúng với MongoDB. Thật vậy, tôi đã thử những cách sau:

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

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

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

Và kết quả là undefined. Trong trường hợp đó, có vẻ như đây không phải là cách để làm như vậy.

Có cách nào để sử dụng mongo db bên trong Node với các lời hứa thay vì gọi lại không?


Câu trả lời:


118

Cách tiếp cận của bạn gần như đúng, chỉ là một sai sót nhỏ trong lập luận của bạn

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) {})

11
Chính xác! MongoDB Node.js lái xe 2.x "Returns: Promise nếu không gọi lại thông qua" ia bằng MongoClient.connect. Nếu bạn có node.js <4 mà không tích hợp sẵn lời hứa ES6 thì bạn cũng có thể sử dụng miếng đệm hứa hẹn tương thích với ES6 hoặc cung cấp triển khai lời hứa tương thích ES6 theo promiseLibrarytùy chọn MongoClient.connect.
VolkerM

5
Dựa trên một số thử nghiệm, nếu bạn kết nối với URL mongodb//localhost:27017(mà không chỉ định cơ sở dữ liệu), bạn sẽ nhận lại mongoclient, vì vậy bạn cần gọi mongoclient.db('example'). Xem mongodb.github.io/node-mongodb-native/api-generated/…
PatS

21

Bạn cũng có thể làm 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
}


Tôi có thể hôn khuôn mặt của bạn ngay bây giờ. Đây là câu trả lời đơn giản nhất, tốt nhất mà tôi đã tìm thấy trong nhiều giờ.
Rob E.

Đây chỉ là câu trả lời đơn giản nhất, mới nhất, đầy đủ nhất và cập nhật nhất có thể. Cảm ơn bạn rất nhiều.
keuluu

19

Vì không có câu trả lời nào ở trên đề cập đến cách thực hiện điều này mà không có bluebird hoặc q hoặc bất kỳ thư viện ưa thích nào khác, hãy để tôi thêm 2 xu vào điều này.

Đây là cách bạn thực hiện chèn với các hứa hẹn ES6 gốc

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

Tôi đã định nghĩa phương thức open () của mình là phương thức trả về một lời hứa. Để thực hiện chèn, đây là đoạn mã của tôi bên dưới

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

Hy vọng rằng sẽ giúp. Nếu bạn có bất kỳ đề xuất nào để cải thiện điều này, hãy cho tôi biết vì tôi sẵn sàng cải thiện bản thân :)


13
Bạn gói một lời hứa trong một lời hứa khác. Các phương thức MongoClient đang trả về một lời hứa rồi và không cần phải gói lại điều này. Đây là một mẫu chống thất hứa điển hình.
westor

4
Sẽ xuất hiện sau nhiều tháng, nhưng câu trả lời của @ Green 20 phút sau bài đăng gốc sử dụng hỗ trợ hứa hẹn gốc của mongodb.MongoClient và không có thư viện hứa không liên quan.
Owen

2
Đây phải là câu trả lời chính xác, vì nó không dựa vào bất kỳ thư viện hứa hẹn nào của bên thứ ba.
GlGuru

@westor làm cách nào bạn sẽ trả về một lời hứa từ phương thức open () mà không cần gói nó trong Lời hứa mới? Tôi nghĩ đây là cách duy nhất.
Abhishek Nalin

1
@AbhishekNalin Phương thức kết nối MongoDB (ít nhất là trong các phiên bản mới hơn) trả về một lời hứa. Do đó, bạn có thể viết 'mongoClient.connect (url) .then (...)' hoặc trong phương thức mở này, bạn sẽ trả về mongoClient.connect (url). Bạn có thể thoát khỏi cuộc gọi lại. Trường hợp lỗi được giải quyết bằng lần bắt cuối cùng ở đây.
westor

11

Đây là câu trả lời chung cho Cách sử dụng MongoDB với các hứa hẹn trong Node.js?

mongodb sẽ trả về một lời hứa nếu tham số gọi lại bị bỏ qua

Trước khi chuyển đổi thành 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)
        });
    }
})

Sau khi chuyển đổi thành 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) {})

Trong trường hợp bạn cần xử lý nhiều yêu cầu

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) {})

1
Tại sao bạn tạo chuỗi lời hứa lồng nhau để hoạt động sau khi kết nối? Tại sao không:MongoClient.connect(uri).then(client => client.db("db").collection("users").find()).then(data => console.log(data)).catch(err => console.log(err));
SerG

Đây sẽ là tốt hơn với các liên kết đến các tài liệu hướng dẫn
mikemaccana

Ký hiệu ngắn hơn cho catch: .catch (console.log)
Benjam

2

CẢNH BÁO Chỉnh sửa:

Như John Culviner đã lưu ý, câu trả lời này không được chấp nhận. Sử dụng trình điều khiển, nó đi kèm với OOTB hứa hẹn.


Nếu bạn chọn sử dụng bluebird làm thư viện hứa hẹn, bạn có thể sử dụng promisifyAll()hàm bluebirds trên 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);
});

6
Trình điều khiển MongoDB đã có lời hứa (nếu bạn muốn bluebird, bạn có thể chỉ định trong các tùy chọn hoặc như tôi đính kèm nó vào global.Promise) KHÔNG LÀM ĐIỀU NÀY!
John Culviner

2

Tôi biết tôi đến bữa tiệc hơi muộn nhưng tôi muốn chia sẻ một ví dụ bằng cách sử dụng 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 };

Tôi đi vào chi tiết hơn một chút ở đây nếu bạn muốn xem:

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


rất đẹp. Tôi sẽ chỉ đổi tên hàm getDbConnection vì nó không trả về kết nối. Nó trả về _db. :)
kroiz

1

Bạn có thể sử dụng một gói thay thế, chẳng hạn như mongodb-promisehoặc quảng bá mongodbAPI gói theo cách thủ công bằng cách xây dựng các lời hứa của riêng bạn xung quanh nó hoặc thông qua một gói tiện ích hứa nhưbluebird.promisify


Trình điều khiển MongoDB đã có lời hứa (nếu bạn muốn bluebird, bạn có thể chỉ định trong các tùy chọn hoặc như tôi đính kèm nó vào global.Promise) KHÔNG LÀM ĐIỀU NÀY!
John Culviner

1

Giải pháp làm việc với phiên bản MongoDB > 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)
    })

0

Bạn cần tạo một lời hứa kết nối với Mongo.

Sau đó, xác định chức năng của bạn có sử dụng lời hứa này: myPromise.then(...).

Ví dụ:

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

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

    });
}

đây là mã đầy đủ:

http://jsfiddle.net/t5hdjejg/


Trình điều khiển MongoDB đã có lời hứa (nếu bạn muốn bluebird, bạn có thể chỉ định trong các tùy chọn hoặc như tôi đính kèm nó vào global.Promise) KHÔNG LÀM ĐIỀU NÀY!
John Culviner

@JohnCulviner theo như tôi có thể nói, .find không trả lại lời hứa? Ví dụ, một số phương thức thực hiện - .count () trên con trỏ - nhưng db.mycoll.find ({}). Thì không xác định?
sil

@sil db.get ("bộ sưu tập"). find ({something: "a"}). then (). catch (); làm việc cho tôi
Rafique Mohammed

0

Đây là một lớp lót để mở kết nối

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

và gọi nó như thế này

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

-1

Có vẻ như phương thức kết nối không có giao diện hứa được xác định

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

bạn luôn có thể tự triển khai nó trong thư viện trình kết nối Mongodb, nhưng điều đó có thể liên quan nhiều hơn những gì bạn đang tìm kiếm.

Nếu bạn thực sự cần làm việc với các hứa hẹn, bạn luôn có thể sử dụng đa điền hứa hẹn ES6:

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

và bọc mã kết nối của bạn với mã đó. Cái gì đó như

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>);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.