Javascript原型不工作 - MongoDB游标

时间:2014-06-02 12:42:59

标签: javascript node.js mongodb socket.io

我正在尝试合并两个项目:

Real-time apps using MongoDB

https://github.com/meanjs/mean

到目前为止它一直很顺利,但我最近遇到了一个我不太了解的问题。我得到的错误是“游标没有方法'intervalEach'”。现在intervalEach是MongoDB Cursor的原型。请参阅以下代码:

'use strict';
/**
 * Module dependencies.
 */
var init = require('./config/init')(),
    config = require('./config/config'),
    mongoose = require('mongoose'),
    emitter = require("events").EventEmitter,
    mongo = require("mongodb"),
    QueryCommand = mongo.QueryCommand,
    Cursor = mongo.Cursor,
    Collection = mongo.Collection,
    http = require('http'),
    url = require('url'),
    fs = require('fs');

/**
 * Main application entry file.
 * Please note that the order of loading is important.
 */

// Heroku-style environment variables
var uristring = process.env.MONGOLAB_URI || "mongodb://localhost/logdb";
var mongoUrl = url.parse (uristring);

// Bootstrap db connection
var db = mongoose.connect(config.db);

// Init the express application
var app = require('./config/express')(db);

// Bootstrap passport config
require('./config/passport')();


// Start the app by listening on <port>
//app.listen(config.port);

// Init Socket.IO
var io = require("socket.io").listen(app.listen(config.port));

// Duck-punching mongodb driver Cursor.each.  This now takes an interval that waits
// "interval" milliseconds before it makes the next object request...
Cursor.prototype.intervalEach = function (interval, callback) {
    var self = this;
    if (!callback) {
        throw new Error("callback is mandatory");
    }

    if (this.state != Cursor.CLOSED) {
        //FIX: stack overflow (on deep callback) (cred: https://github.com/limp/node-mongodb-native/commit/27da7e4b2af02035847f262b29837a94bbbf6ce2)
        setTimeout(function () {
            // Fetch the next object until there is no more objects
            self.nextObject(function (err, item) {
                if (err != null) return callback(err, null);

                if (item != null) {
                    callback(null, item);
                    self.intervalEach(interval, callback);
                } else {
                    // Close the cursor if done
                    self.state = Cursor.CLOSED;
                    callback(err, null);
                }

                item = null;
            });
        }, interval);
    } else {
        callback(new Error("Cursor is closed"), null);
    }
};

//
// Open mongo database connection
// A capped collection is needed to use tailable cursors
//
mongo.Db.connect(uristring, function (err, db) {
    console.log("Attempting connection to " + mongoUrl.protocol + "//" + mongoUrl.hostname + " (complete URL supressed).");
    db.collection("log", function (err, collection) {
        collection.isCapped(function (err, capped) {
            if (err) {
                console.log("Error when detecting capped collection.  Aborting.  Capped collections are necessary for tailed cursors.");
                process.exit(1);
            }
            if (!capped) {
                console.log(collection.collectionName + " is not a capped collection. Aborting.  Please use a capped collection for tailable cursors.");
                process.exit(2);
            }
            console.log("Success connecting to " + mongoUrl.protocol + "//" + mongoUrl.hostname + ".");
            startIOServer(collection);
        });
    });
});


//
// Bind send action to "connection" event
//
function startIOServer(collection) {
    console.log("Starting ...");

    // for testing
    Cursor.intervalEach(300,function(err,item){

    });
    // Many hosted environments do not support all transport forms currently, (specifically WebSockets).
    // So we force a relatively safe xhr-polling transport.
    // Modify io.configure call to allow other transports.

    /*io.configure(function () {
        io.set("transports", config[platform].transports); // Set config in ./config.js
        io.set("polling duration", 10);
        io.set("log level", 2);
    });*/
    io.sockets.on("connection", function (socket) {
        readAndSend(socket, collection);
    });
};

//
// Read and send data to socket.
// The real work is done here upon receiving a new client connection.
// Queries the database twice and starts sending two types of messages to the client.
// (known bug: if there are no documents in the collection, it doesn't work.)
//
function readAndSend(socket, collection) {
    collection.find({}, {"tailable": 1, "sort": [
        ["$natural", 1]
    ]}, function (err, cursor) {
        console.log(cursor)
        cursor.intervalEach(300, function (err, item) { // intervalEach() is a duck-punched version of each() that waits N milliseconds between each iteration.
            if (item != null) {
                socket.emit("all", item); // sends to clients subscribed to type "all"
            }
        });
    });
    collection.find({"messagetype": "complex"}, {"tailable": 1, "sort": [
        ["$natural", 1]
    ]}, function (err, cursor) {
        cursor.intervalEach(900, function (err, item) {
            if (item != null) {
                socket.emit("complex", item); // sends to clients subscribe to type "complex"
            }
        });
    });
};




// Expose app
exports = module.exports = app;

// Logging initialization
console.log('LogFusion application started on port ' + config.port);

据我所知,这是正确实施的。如果你在第一个链接中查看项目,它们的实现工作正常,所以我不太确定我做错了什么。

我的完整源代码可以在这里抓取:LogFusion - Github

3 个答案:

答案 0 :(得分:1)

我们也遇到了这个问题,并且恢复到mongodb驱动程序的1.2版本对我们不起作用。在当前默认版本的驱动程序中(根据npm为1.4.6),由于https://github.com/mongodb/node-mongodb-native/blob/1.4/lib/mongodb/scope.js,您完全合理的代码将无效。呻吟。感谢指针@Esailija。

答案 1 :(得分:1)

我从Mongo用户组中恢复了一些旧的demo code时遇到了这个问题。似乎intervalEach构造已经被废除了(更惯用的)节点事件模型。

这适用于最新的socket.io(1.0.6)和mongodb(1.4.7)

var dataStream = collection.find({}, {tailable: true, awaitdata: true}).stream();

dataStream.on('data', function(data) { 
    // do something with the data
});

dataStream.on('error', function(error) { 
    // handle error
});

Jaan Paljasma还有一个更全面的要点on githubblog article

答案 2 :(得分:0)

这是由于MongoDB和Socket.IO的版本控制问题

如果我使用&#34; mongodb&#34;:&#34; 1.2.13&#34;和&#34; socket.io&#34;:&#34; 0.9.13&#34;,然后它工作正常