为什么我在node.js类中得到未定义的实例?

时间:2015-01-27 07:57:52

标签: javascript node.js mongodb

我是node.js的新手。我正在尝试为node.js类定义一个构造函数,它基本上从mongo db中获取数据。相同的代码如下

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

var ObjectID = require('mongodb').ObjectID;
var mongoHost = 'localHost';
var mongoPort = 27017;

CollectionDriver = function(db) {
    this.db = db;
    console.log("Collection drive has been set");
};

CollectionDriver = function() {
    var mongoClient = new MongoClient(new Server(mongoHost, mongoPort));
    mongoClient.open(function(err, mongoClient) {
        if (!mongoClient || err) {
            console.error("Error! Exiting... Must start MongoDB first");
            process.exit(1);
        }
        var db1 = mongoClient.db("Quiz");
        this.db = db1;
        console.log("Set Collection Driver by default");
    });
};

CollectionDriver.prototype.getCollection = function(collectionName, callback) {
    this.db.collection(collectionName, function(error, the_collection) {
        if (error) callback(error);
        else callback(null, the_collection);
    });
};
//find all objects for a collection
CollectionDriver.prototype.findAll = function(collectionName, obj, callback) {
    this.getCollection(collectionName, function(error, the_collection) {
        if (error) callback(error);
        else {
            the_collection.find(obj).toArray(function(error, results) {
                if (error) callback(error);
                else {
                    console.dir(results);
                    callback(null, results);
                }

            });
        }
    });
};

我试图在其他类中使用它,如下所示:

CollectionDriver = require('./collectionDriver').CollectionDriver;
var collectionDriver = new CollectionDriver(db);
OtherClassName.prototype.find = function(credentials, callback) {

    collectionDriver.findAll("user_groups", credentials, function(error, results) {

        if (!error) {
            // Do something
        }
    });

    // ...

每当我尝试访问Otherclass的find方法时,它都说上面的类的db变量(即ConnectionDriver)是未定义的。但是我可以看到ConnectionDriver构造函数正确执行并且正确打开了与db的连接,并且this.db=db1也被执行了。我做错了什么?任何帮助将不胜感激

2 个答案:

答案 0 :(得分:1)

在敲打我的头并投入(浪费)一整天之后。我意识到了这个问题。实际上mongoClient.open()调用是一个异步调用,我甚至在打开db / getting db实例之前就返回了CollectionDriver对象。

我通过在构造函数外部移动db调用并设置实例db来解决了这个问题。修改后的代码如下:

var db = null;
var mongoClient = new MongoClient(new Server(mongoHost, mongoPort));
mongoClient.open(function(err, mongoClient) {
    if (!mongoClient || err) {
        console.error("Error! Exiting... Must start MongoDB first");
        process.exit(1);
    }
    db = mongoClient.db("Quiz");

});

CollectionDriver = function() {
console.log("Set Collection Driver by default");
};

上面的代码似乎有效,但是当我将db实例分配给this.db而不是如上所述明确声明变量时,我得到相同的undefined / null错误(当我将db变量初始化为null时)。有什么想法为什么这个行为?

答案 1 :(得分:0)

这已经回答了,但我相信正确的答案是,this在函数调用中被重新定义。在要打开的回调函数内部,现在指向该函数。解决这个问题的方法是使用ES6箭头函数,如果你在节点4 +上。

collectionDriver = function() {
var mongoClient = new MongoClient(new Server(mongoHost, mongoPort));
mongoClient.open((err, mongoClient) => {
    if (!mongoClient || err) {
        console.error("Error! Exiting... Must start MongoDB first");
        process.exit(1);
    }
    var db1 = mongoClient.db("Quiz");
    this.db = db1;
    console.log("Set Collection Driver by default");
});

注意:function (err, mongoClient) {已更改为(err, mongoClient) => {

this然后按预期行事。