【问题标题】:No data written in Mongo database after Process.Exit()Process.Exit() 后没有数据写入 Mongo 数据库
【发布时间】:2014-10-10 04:59:51
【问题描述】:

我正在编写一个 node.js 脚本来将一些来自 MySQL 数据库的数据写入 MongoDB 数据库。它不是一个网络应用程序,而是一个本地脚本(我的 MySQL 和 Mongo 都是本地的)。

问题是当所有数据都写入后,脚本并没有终止。我必须用 CTRL+C 关闭它。但是我所有的数据都写在我的 MongoDB 数据库中。

我在 MongoDB 中编写后调用的回调末尾添加了一个“process.exit()”行。应用程序终止,但没有写入数据!我不明白为什么。

这是相关的代码部分

(...)
var req = "SELECT * FROM geometry";

// "connection" is a MySQL connection
connection.query(req, function(err, rows, fields) {
    console.log("number of lines :" + rows.length);
    connection.end();

    if (err) {
        throw err;
    }
    // "Entry" is my model
    for (var i = 0; i < rows.length; i++) {
        Entry.create({
            "code" : rows[i].code,
            "name" : rows[i].name,
            "coords" : rows[i].coords,
            "type" : rows[i].type
        }, function(err, doc){
            if (err) {
                throw (err);
            }
        });
    }

    console.log("end");
    process.exit(); // no data written ! why ?
});

你能帮帮我吗? 提前致谢。

【问题讨论】:

  • 看来你不习惯异步思考。试着阅读这个问题和答案,看看你是否明白你在你的案例中是如何犯同样的错误的:stackoverflow.com/questions/23667086/…
  • 感谢您的回答,您的链接在我的大脑中点亮了灯 :)

标签: node.js mongodb asynchronous mongoose


【解决方案1】:

问题是您过早终止进程。您无需等待mongoose 将您的任何文档实际发送到 MongoDB。以下是一些如何正确执行此操作的示例。

注意请先read this question了解为什么没有写入数据,然后阅读我的回答以了解如何处理 .


使用承诺和when.js 模块

首先我们应该需要when 模块(或任何其他基于promise 的控制流模块,例如Qbluebird)。

when = require('when');

然后我们可以用它来简化我们的代码:

promises = rows.map(function(row) {
  return Entry.create(row);
})
when.all(promises).otherwise(console.error).ensure(function() {
  process.exit()
})

或使用when.map:

when.map(rows, function(row) {
  return Entry.create(row);
}).otherwise(console.error).ensure(function() {
  process.exit()
})

注意此解决方案可能会染上猫鼬build-in promises support


使用async.js 模块

async.js 是 node.js 的基于回调的控制流模块:

async = require('async');

但它几乎和 Promise 一样强大:

async.map(roes, function(row, next) {
  Entry.create(row, next);
}, function(err){
  if (err) throw (err);
  process.exit();
});

使用纯 JavaScript

但是我们可以使用纯基于回调的 JavaScript 实现相同的结果:

var pending = 0;
rows.forEach(function(row) {
  pending++;
  Entry.create(row, function(err) {
    if (err) throw (err);
    if (--pending === 0) process.exit();
  });
});

注意mongoose

Bu默认猫鼬使用strict mode,所以我只是调用

Entry.create(row);

知道 mongoose 会删除 row 的任何属性,而 Entry 架构中不存在这些属性。


关于异步代码和控制流模块的说明

控制流模块(promises、async.js 等)可帮助您处理异步代码,但如果您不熟悉 node.js 和异步编程,我建议您从纯 JS 方法开始以了解 node .js 更好。那么采用一些控制流解决方案是安全的。

您还应该注意,Promise 为您的异步代码提供了一个巨大的抽象层,其中包含大量语法糖,而基于回调的模块(如 async.js)只提供了一小部分。

所以,在我看来,掌握 node.js 的最佳方法如下:

Pure JS -> callback-based modules (async.js) -> promises

最新的 node.js 0.11.x(带有--harmony 标志)也支持generators,提供了另一种处理异步代码的方法。

【讨论】:

  • 好的,我知道了。所以我会尝试纯JS的方法。我想我必须跟踪创建的用户数,并在 Create() 回调中发送一个 process.exit(),只要这个数字等于我的 MySQL 数据集的行数?
猜你喜欢
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-25
相关资源
最近更新 更多