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

Why am I getting undefined instance in node.js class?

我是 node.js 的新手。我正在尝试为 node.js class 定义一个构造函数,它基本上从 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);
                }

            });
        }
    });
};

我正在尝试在其他 class 中使用它,如下所示:

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 方法时,它都会说上面 class(即 ConnectionDriver)的 db 变量未定义。但是我可以看到 ConnectionDriver 构造函数正在正确执行并且与数据库的连接已正确打开并且 this.db=db1 也正在运行 executed.Am 我做错了什么?任何帮助将不胜感激

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

我通过在构造函数外部打开 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 变量初始化为无效的)。想知道为什么会出现这种行为吗??

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

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 然后按预期运行。