nodeJS中的module.exports问题

时间:2015-12-18 09:36:23

标签: javascript node.js csv module

我正在练习node.js,我有一些疑问。

我有一个csv文件(users.csv),我创建了一个节点模块(library.js)来返回csv文件中的值。当我从我的程序中调用模块时,我得到了结果。我的计划如下。

users.csv

id,name
1,Jim
2,Jo

library.js

var csv             = require("fast-csv");
var DataToBeReturned = [];
exports.users = function () {
        csv.fromPath("users.csv", {headers: true})
        .on("data",function(data){
            DataToBeReturned.push(data);
        })
        .on("end",function(){   
            console.log(DataToBeReturned.length);
            return DataToBeReturned;
        });
};

app.js

var mylibrary = require('./library.js');
console.log(mylibrary.users());
console.log(mylibrary.users());

我的预期输出是

2
[{ id: '1', name: 'Jim' },{ id: '2', name: 'Jo' }]
2
[{ id: '1', name: 'Jim' },{ id: '2', name: 'Jo' }]

相反,我得到了

undefined
undefined
3
4

我的怀疑:

  1. 为什么返回值未定义?
  2. 为什么我的计数不总是2?
  3. 提前致谢。

1 个答案:

答案 0 :(得分:1)

我自己无法测试您的代码,但是通过阅读您的代码,您遇到了两个问题,这些问题与您的问题密切相关。

首先,您遇到了大多数人在使用nodejs时遇到的典型问题。您正在同步调用异步函数。这就是为什么它的前两次打印未定义,你打印调用用户的结果。由于用户还没有完成运行,它的值是未定义的。您应该使用回调实现library.js函数用户。例如:

exports.users = function (callback) {
    csv.fromPath("users.csv", {headers: true})
    .on("data",function(data){
        DataToBeReturned.push(data);
    })
    .on("end",function(){   
        console.log(DataToBeReturned.length);
        return callback(null, DataToBeReturned);
    });
};

然后在app.js中,您将实现此操作以使用回调。

var csv             = require("fast-csv");
// err is just a nodejs convention, if you add error checking to users,
// instead of throwing an error, you would pass it back as the first agrument
// to the callback
mylibrary.users(function(err, users) {
    console.log(users);
});
mylibrary.users(function(err, users) {
    console.log(users);
});

其次,您指的是users函数中的全局变量。那就是你打印出3和4.两个调用都立即对变量进行操作。当第一个调用完成并返回值时,第二个调用也已经修改了数组。因此,您希望移动数组声明而不是函数,因此只有那里的代码才能访问它。

exports.users = function () {
    var DataToBeReturned = [];
    // the rest of your code.
};

编辑:模块内的代码被缓存,因此只执行一次。然后,引用它的每个脚本都只返回该副本。如果您只需要阅读一次csv,请使用此功能。

var DataToBeReturned = [];
var called = false;
function read(callback) {
    if (called) {
        process.nextTick(function() {
            return callback(null, DataToBeReturned);
        });
        return;
    } else {
        called = true;
        csv.fromPath("users.csv", {headers: true})
        .on("data",function(data){
            DataToBeReturned.push(data);
        })
        .on("end",function(){   
            console.log(DataToBeReturned.length);
            return callback(null, DataToBeReturned);
        });
    }
};

exports.users = function(callback) {
    return read(callback);
};

process.nextTick部分很重要,有关其工作原理的更多信息可以在文档中找到here