【问题标题】:Warning from mongodb - "(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate..."来自 mongodb 的警告 - “(节点)警告:检测到递归 process.nextTick。这将在下一个版本的节点中中断。请使用 setImmediate ...”
【发布时间】:2014-03-02 17:20:54
【问题描述】:

在那里,

我正在运行节点 0.10.24,我正在尝试从 mongodb 集合中获取所有记录,一旦我的集合超过 1000 个元素,我就会收到此错误:

node.js:375 抛出新的错误(味精); ^ 错误:(节点)警告:检测到递归 process.nextTick。这将在下一个版本的节点中中断。请使用 setImmediate 进行递归延迟。 在 maxTickWarn (node.js:375:15) 在 process.nextTick (node.js:480:9) 在 CursorStream._next (/var/www/html/node_modules/mongodb/lib/mongodb/cursorstream.js:76:11) 在 CursorStream._onNextObject (/var/www/html/node_modules/mongodb/lib/mongodb/cursorstream.js:98:8) 在 /var/www/html/node_modules/mongodb/lib/mongodb/cursorstream.js:78:12 在 Cursor.nextObject (/var/www/html/node_modules/mongodb/lib/mongodb/cursor.js:540:5) 在 /var/www/html/node_modules/mongodb/lib/mongodb/cursorstream.js:77:18 在 process._tickCallback (node.js:415:13)

我尝试了两种从 mongodb 获取数据的方法,但均未成功。

版本 1:

exports.findAll = function(req, res) {
db.collection('products', function(err, collection) {
    var first = true;

    var stream = collection.find().batchSize(10000).stream();
    var results = [];

    stream.on('data', function(item){
        results.push(item);
    }).on('error', function (err) {
        // handle the error
        console.log(err);
    }).on('close', function () {
        // the stream is closed, so complete the response with res.end();
        res.send(results);
    });
});
};

版本 2:

var sys = require('sys'),
http = require('http'),
mongodb = require('mongodb');

var server = new mongodb.Server("localhost", 27017, {});
var db = new mongodb.Db('productdb', server, {});
var client  = null

db.open(function (error, clientParam) {
    if (error) {
            db.close();
            throw error;
    }
    client = clientParam;
});

http.createServer(function(req, res) {
    var collection = new mongodb.Collection(client, 'products');

    collection.find({}, {}, function(err, cursor) {
            if(err == null){
             cursor.toArray(function(err, docs){
                     res.writeHead(200, {'Content-Type': 'application/json'});
                     res.write(docs);
                     res.end();
                     //console.log(docs);
             });
            }else{
                    res.writeHead(200, {'Content-Type': 'text/html'});
                res.write('An error occurred!');
                res.end();
                throw err;
            }
    });
    }).listen(8088);

在版本 3 中,当我添加流暂停并在超时后恢复它时,我会得到我想要的结果,但会有很大的延迟。

版本 3:

exports.findAll = function(req, res) {
db.collection('products', function(err, collection) {
    var first = true;

    var stream = collection.find().batchSize(10000).stream();
    var results = [];

    stream.on('data', function(item){
        results.push(item);
        stream.pause();

        setTimeout(function(){
            stream.resume();
        }, 1);
    }).on('error', function (err) {
        // handle the error
        console.log(err);
    }).on('close', function () {
        // the stream is closed, so complete the response with res.end();
        res.send(results);
    });

});
};

什么是读取大量行的正确方法,使用node.js从mongodb非常快而不会遇到这个问题?

谢谢。

更新:

我找到了另一种仍然不起作用的方法,但是这次它在返回第 500 行后给了我这个警告:

[WARNING] streamRecords method is deprecated, please use stream method which is much faster

代码如下:

db.collection('products', function(err, collection) {

    var stream = collection.find().streamRecords();
    var results = [];

    stream.on('data', function(item){
        results.push(item);
    }).on('error', function (err) {
        // handle the error
        console.log(err);
    }).on('end', function () {
        // the stream is closed, so complete the response with res.end();
        res.send(results);
    });
});

如果我将 streamRecords() 调用更改为 stream(),我会回到版本 1 中的初始问题。如果我这样离开它,我只会得到前 500 行。 :|

【问题讨论】:

    标签: node.js node-mongodb-native


    【解决方案1】:

    经过 3 天的努力,我决定在我的服务器上进行全新安装,并在安装了所有最新最好的版本之后:

        "express": "3.x",
        "mongodb": "1.3.23",
        "connect-timeout": "0.0.1"
        "npm": "1.x"
    

    我之前的 node.js 版本的 mongodb 驱动程序是:1.1.8,我认为这是造成我悲痛的原因。

    我的版本 1 就像一个魅力!

    【讨论】:

      【解决方案2】:

      只是想知道在光标上使用 each 是否会出现同样的问题。因此,只需对您的代码进行一些轻微的编辑(显然更改了序列化位,但只是显示了放置):

      http.createServer(function(req, res) {
      var collection = new mongodb.Collection(client, 'products');
      
      collection.find({}, {}, function(err, cursor) {
          if(err == null){
              res.writeHead(200, {'Content-Type': 'application/json'});
      
              cursor.each(function(err, doc){
                  if (doc != null) {
                      res.write(doc);
                  }
              });
      
              res.end();
              //console.log(docs);
      
           }else{
               res.writeHead(200, {'Content-Type': 'text/html'});
               res.write('An error occurred!');
               res.end();
              throw err;
           }
      });
      }).listen(8088);
      

      【讨论】:

      • 嗨 Neil,我收到 res.write(doc) 的以下错误; line: http.js:853 throw new TypeError('第一个参数必须是字符串或缓冲区'); ^ TypeError: first argument must be a string or Buffer at ServerResponse.OutgoingMessage.write (http.js:853:11) 我会尝试研究它,看看是什么原因造成的。
      • 我将该行更改为:“res.write(JSON.stringify(doc));”现在我再次遇到同样的错误:错误:(节点)警告:检测到递归 process.nextTick。看来我陷入了这个恶性循环。 :(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-24
      • 2018-08-10
      相关资源
      最近更新 更多